Silver Cow Party
POJ - 3268
题目的大意是说在2号点有一个party,所有其他点的牛都要去,同时也要回来,求在所有的牛来回的最短时间内最大值是多少。
一开始我是用了最容易想到的方法,从其他点到x点,再从x点到其他点这样一次次的遍历一遍,想想都成三层for循环了,结果肯定就是TLE》==《了,用了邻接表,同样TLE,没办法看了一下题解,原来很简单,将图倒过来记一次,正着记一次不就行了。
但是其中有一些要注意的地方,废话不说,上代码:
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<iomanip>
#include<queue>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;i++)
int e[1005][1005];
//int first[1010];
//int next[1010];
//int u[100005];
//int v[100005];
//int w[100005];
bool book[1005];
int disg[1005];//代表其他点去x点的最小距离
int disb[1005];//代表x点到其他点的最小距离
int MAX=0x3f3f3f3f;
int n,m,x;
int Dijkstra()
{
memset(disb,0,sizeof(disb));
memset(disg,0,sizeof(disg));
rep(i,1,n)
e[i][i]=0;
// int k=first[star];
// while(k!=-1)
// {
// dis[v[k]]=w[k];
// k=next[k];
// }
rep(i,1,n)
disg[i]=e[i][x];//这里是从i-->x,因此下面是e[k][u]
memset(book,0,sizeof(book));
book[x]=1;
rep(i,1,n)
{
int MIN=MAX;
int u;
rep(j,1,n)
if(!book[j]&&disg[j]<MIN)
MIN=disg[u=j];
book[u]=1;
rep(k,1,n)
{
if(e[k][u]<MAX&&!book[k])
disg[k]=min(disg[k],disg[u]+e[k][u]);
}
// int k=first[u];
// while(k!=-1)
// {
// dis[v[k]]=min(dis[v[k]],dis[u]+w[k]);
// k=next[k];
// }
//
}
memset(book,0,sizeof(book));//这里一定要从新初始化
rep(i,1,n)
disb[i]=e[x][i];//这里是从x-->i,因此下面是e[u][k]
book[x]=1;
rep(i,1,n)
{
int MIN=MAX;
int u;
rep(j,1,n)
if(!book[j]&&disb[j]<MIN)
MIN=disb[u=j];
book[u]=1;
rep(k,1,n)
{
if(e[u][k]<MAX&&!book[k])
disb[k]=min(disb[k],disb[u]+e[u][k]);
}
}
int ans=0;
rep(i,1,n)
ans=max(disb[i]+disg[i],ans);
return ans;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n>>m>>x;
memset(e,MAX,sizeof(e));
rep(i,1,m)
{
int X,y,v;
cin>>X>>y>>v;
e[X][y]=v;
}
cout<<Dijkstra()<<endl;
//memset(first,-1,sizeof(first));
// rep(i,1,m)
// {
// cin>>u[i]>>v[i]>>w[i];
// next[i]=first[u[i]];
// first[u[i]]=i;
// }
return 0;
}