题目链接:http://poj.org/problem?id=3268
题意:
有编号为1-N的牛,它们之间存在一些单向的路径。给定一头牛的编号,其他牛要去拜访它并且拜访完之后要返回自己原来的位置,求这些牛中所花的最长的来回时间是多少。
思路:
很骚的写法,这里用了两个数组标记,head,next,他每次找到下一个结点后,head就赋给next了,然后head又是一条新的边,这样,我在遍历这个链表的时候,就能从后往前遍历了,我推了一个小时。
然后这里的if语句也很重要,要先松弛,再看前一个结点有没有被访问,没有被访问就加到队列里去,并标记。这里我Debug7小时才发现这个错误。内心是崩溃的。
#include <stdio.h> #include <string.h> #include <queue> using namespace std; #define N 1005 #define M 2000010 #define INF 0x3f3f3f3f int head[M],next[500050]; int dis[N]; int cnt[N]; bool vis[N]; int n,m,send,x1,y1; int e; struct Node { int u; int v; int c; Node() {} Node(int u,int v,int c) : u(u),v(v),c(c) {} } nodes[M]; void addNode(int u,int v,int c) { nodes[e] = Node(u,v,c); next[e] = head[u]; head[u] = e++; } void init() { memset(head,-1,sizeof(head)); memset(next,-1,sizeof(next)); memset(cnt,0,sizeof(cnt)); e = 1; for(int i=0; i<m; i++) { int u,v,c; scanf("%d%d%d",&u,&v,&c); addNode(u,v,c); //addNode(v,u,c); } } bool relax(int u,int v,int c) { if(dis[v]>dis[u]+c) { dis[v] = dis[u] + c; return true; } return false; } int spfa(int src,int send) { memset(vis,false,sizeof(vis)); for(int i=1; i<=n; i++) dis[i] = INF; dis[src] = 0; vis[src] = true; queue<int> Q; Q.push(src); while(Q.size()) { int f = Q.front(); Q.pop(); vis[f] = false; for(int i=head[f]; i+1; i=next[i]) { if(relax(f,nodes[i].v,nodes[i].c)&&!vis[nodes[i].v]) { //if((++cnt[Nodes[i].v]>n)) return -1; Q.push(nodes[i].v); vis[nodes[i].v] = true; } } } return dis[send]; } int main() { scanf("%d%d%d",&n,&m,&send); init(); int tmp = -0x3f3f3f3f; for(int i=1; i<=n; i++) { if(i==send) continue; x1 = spfa(i,send); y1 = spfa(send,i); if(tmp<(x1+y1)) tmp = x1+y1; } printf("%d ",tmp); return 0; }