poj 3268(Dijkstra+有向圖的處理)
阿新 • • 發佈:2019-02-03
Silver Cow Party
題目的大意是說在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; }