题意:草场上有n个农场,农场之间有一些路径,每个农场里住着一头牛,现在x农场的牛要过生日开party,其他农场的牛要到该农场去参加party,
现在让你选择一头来回耗时最多的一头牛出来,输出时间。给你一个n个结点、m条边的有向图,现在要你求从n-1个结点到达指定的一个结点的来回最长路
思路:如果返程的部分是从n求向1的就要求n次所以,我们把边全部反向一边再来求;
但是使用链式向前星的时候遇到一个问题,就是如何逆置边。
就想到了使用标记变量,一个正向(1)一个逆向(0) ; 当我们第一次正向过去遍历时,遇到flag =0 的边就跳过, 反之 第二遍遇到flag = 1 的边就跳过
一开始TLE了半天一直找不到问题,然后随手乱改就把 Q.size()这个判断改成 !Q.empty() 就过了...
完整代码:
#include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using namespace std; const int inf = 0x3f3f3f3f; const int max_size = 1e3+10; const int max_edge = 1e5+5; typedef pair<int,int> pi; struct Edge{ int u; int v,w,next; int flag ; }edge[max_edge<<1]; int head[max_size]; int dist[max_size]; int back[max_size]; int top; int n,m; void init(){ memset(dist,inf,sizeof(dist)); memset(head,-1,sizeof(head)); memset(back,inf,sizeof(back)); } void add(int u,int v,int w){ //即把两种都链接上,然后对应关系进行跳过 edge[top].u = u; edge[top].v = v; edge[top].w = w; edge[top].flag = 1; edge[top].next = head[u]; head[u] = top++; edge[top].v = u; edge[top].u = v; edge[top].w = w; edge[top].flag= 0; edge[top].next= head[v]; head[v]=top++; } void dijkstra(int s,bool flag){ priority_queue<pi>Q; Q.push(make_pair(0,s)); while(!Q.empty()){ s = Q.top().second; Q.pop(); for(int i = head[s]; ~i;i = edge[i].next){ if(flag){//跳过 if(!edge[i].flag) continue; } else{ if(edge[i].flag) continue; } if(flag){ if(dist[edge[i].v]>dist[s]+edge[i].w){ dist[edge[i].v] = dist[s]+edge[i].w ; Q.push(make_pair(-dist[edge[i].v],edge[i].v)); } }else{ if(back[edge[i].v]>back[s]+edge[i].w){ back[edge[i].v] = back[s]+edge[i].w ; Q.push(make_pair(-back[edge[i].v],edge[i].v)); } } } } } int main(){ int s; while(cin>>n>>m>>s) { init(); for(int i=0;i<m;i++){ int u,v,w; cin>>u>>v>>w; add(u,v,w); } back[s] = dist[s] = 0; dijkstra(s,1); dijkstra(s,0); int ans = -1; for(int i= 1;i<=n;i++){ if(i == s) continue; ans = max(ans,back[i]+dist[i]); } cout<<ans<<endl; } }