Description
Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T。这些城镇之间通过R条道路 (1 <= R <= 50,000,编号为1到R) 和P条航线 (1 <= P <= 50,000,编号为1到P) 连接。每条道路i或者航线i连接城镇A_i (1 <= A_i <= T)到B_i (1 <= B_i <= T),花费为C_i。对于道路,0 <= C_i <= 10,000;然而航线的花费很神奇,花费C_i可能是负数(-10,000 <= C_i <= 10,000)。道路是双向的,可以从A_i到B_i,也可以从B_i到A_i,花费都是C_i。然而航线与之不同,只可以从A_i到B_i。事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台 了一些政策保证:如果有一条航线可以从A_i到B_i,那么保证不可能通过一些道路和航线从B_i回到A_i。由于FJ的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇S(1 <= S <= T) 把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。
Input
* 第1行:四个空格隔开的整数: T, R, P, and S * 第2到R+1行:三个空格隔开的整数(表示一条道路):A_i, B_i 和 C_i * 第R+2到R+P+1行:三个空格隔开的整数(表示一条航线):A_i, B_i 和 C_i
Output
* 第1到T行:从S到达城镇i的最小花费,如果不存在输出"NO PATH"。
Sample Input
6 3 3 4
1 2 5
3 4 5
5 6 10
3 5 -100
4 6 -100
1 3 -10
样例输入解释:
一共六个城镇。在1-2,3-4,5-6之间有道路,花费分别是5,5,10。同时有三条航线:3->5,
4->6和1->3,花费分别是-100,-100,-10。FJ的中心城镇在城镇4。
Sample Output
NO PATH
NO PATH
5
0
-95
-100
样例输出解释:
FJ的奶牛从4号城镇开始,可以通过道路到达3号城镇。然后他们会通过航线达到5和6号城镇。
但是不可能到达1和2号城镇。
思路:
因为有负权边,所以不能使用dijstra,但是这个数据量使用spfa会t,所以我们考录heap+dijstra。
如何解决负权边呢??注意题目:如果有一条航线可以从A_i到B_i,那么保证不可能通过一些道路和航线从B_i回到A_i。
这就说明,单向边一定不会形成环。
所以一个联通块中,不可能有一个起点和终点都在这个强联通块的单向边,然且对于两个强连通块,只能出项从一个块指向另一个块的单向边,若相互指向,则会形成环
那么对于一个联通块,我们可以只考虑双向边,直接使用dijstra,然后对从这个联通块发出的单向边进行更新,更新其他联通块中的dist,然后把处理过的单向边抹去。
因为是从s到其他点的距离,所以如果从一个联通块,没有单向边指向它,并且还不是s所在联通块,那么它里面的点都是无法到达的(显然)
①所以,我们可以按照拓扑序进行更新,每处理完一个联通块,和其单向边,我们就消除单向边造成的入度,然后进行拓扑排序选择联通块。
这样写法s所在联通块并不一定第一个入队,但是其前入队的联通块最短路无法更新,只能消除单向边,写法清晰。
②我们也一开始可以就把s的联通块号传入,这样的话,其他入度为0的联通块指出的单向边,我们直接需要将其抹去,消除无效联通块对其他联通快造成的入度。
因为其他入度为0的联通块,是无效的。(代码注释部分)
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 int t,r,p,s; 5 typedef pair<int,int> pii; 6 const int maxn = 5e4+5; 7 vector<int>belong[maxn]; 8 struct Node 9 { 10 int x,y,val,next; 11 Node(int x=0,int y=0,int val=0,int next=0):x(x),y(y),val(val),next(next) {} 12 } node[2][maxn<<2]; 13 14 int head[2][maxn]; 15 int cnt[2]; 16 int tot; 17 void add(int x,int y,int val,int t) 18 { 19 node[t][++cnt[t]].x = x; 20 node[t][cnt[t]].y = y; 21 node[t][cnt[t]].val = val; 22 node[t][cnt[t]].next = head[t][x]; 23 head[t][x] = cnt[t]; 24 } 25 int cn[maxn]; 26 int ind[maxn]; 27 int dist[maxn]; 28 bool vis[maxn]; 29 void dfs(int x) 30 { 31 cn[x] = tot; 32 belong[tot].push_back(x); 33 for(int i=head[0][x]; i; i=node[0][i].next) 34 { 35 int y = node[0][i].y; 36 if(cn[y]) 37 continue; 38 dfs(y); 39 } 40 } 41 void solve(int s) 42 { 43 queue<int>que; 44 while(!que.empty()) 45 que.pop(); 46 for(int i=1; i<=tot; i++) 47 if(!ind[i]) 48 que.push(i); 49 // for(int i=1; i<=tot; i++) 50 // { 51 // if(!ind[i] && i != cn[s]) 52 // { 53 // for(int j=0; j<belong[i].size(); j++) 54 // { 55 // for(int k=head[1][belong[i][j]]; k; k=node[1][k].next) 56 // { 57 // --ind[cn[node[1][k].y]]; 58 // } 59 // } 60 // ind[i] = -1; 61 // //printf("%d ------ %d ",ind[i],i); 62 // i=0; 63 // } 64 // } 65 // que.push(cn[s]); 66 memset(dist,0x3f,sizeof(dist)); 67 dist[s] = 0; 68 priority_queue<pii,vector<pii>,greater<pii> >p; 69 while(!que.empty()) 70 { 71 int k = que.front(); 72 que.pop(); 73 while(!p.empty()) 74 p.pop(); 75 int len = belong[k].size(); 76 for(int i=0; i<len; i++) 77 { 78 if(dist[belong[k][i]] < 0x3f3f3f3f) 79 p.push(pii(dist[belong[k][i]],belong[k][i])); 80 } 81 while(!p.empty()) 82 { 83 pii t = p.top(); 84 p.pop(); 85 if(vis[t.second]) 86 continue; 87 vis[t.second] = 1; 88 for(int i=head[0][t.second]; i; i=node[0][i].next) 89 { 90 if(dist[t.second] + node[0][i].val < dist[node[0][i].y]) 91 { 92 dist[node[0][i].y] = dist[t.second] + node[0][i].val; 93 p.push(pii(dist[t.second] + node[0][i].val,node[0][i].y)); 94 } 95 } 96 for(int i=head[1][t.second]; i; i=node[1][i].next) 97 { 98 dist[node[1][i].y] = min(dist[node[1][i].y],dist[t.second]+node[1][i].val); 99 } 100 } 101 for(int i=0; i<len; i++) 102 { 103 for(int j=head[1][belong[k][i]]; j; j=node[1][j].next) 104 { 105 if(--ind[cn[node[1][j].y]] == 0) 106 que.push(cn[node[1][j].y]); 107 } 108 } 109 } 110 } 111 112 int main() 113 { 114 cnt[0] = cnt[1] = 0; 115 scanf("%d%d%d%d",&t,&r,&p,&s); 116 for(int i=1; i<=t; i++) 117 belong[i].clear(); 118 for(int i=1; i<=r; i++) 119 { 120 int u,v,k; 121 scanf("%d%d%d",&u,&v,&k); 122 add(u,v,k,0); 123 add(v,u,k,0); 124 } 125 126 for(int i=1; i<=p; i++) 127 { 128 int u,v,k; 129 scanf("%d%d%d",&u,&v,&k); 130 add(u,v,k,1); 131 } 132 tot = 0; 133 for(int i=1; i<=t; i++) 134 { 135 if(!cn[i]) 136 { 137 tot++; 138 dfs(i); 139 } 140 } 141 142 143 for(int i=1; i<=cnt[1]; i++) 144 { 145 ind[cn[node[1][i].y]]++; 146 } 147 solve(s); 148 for(int i=1; i<=t; i++) 149 { 150 if(dist[i] == 0x3f3f3f3f) 151 printf("NO PATH "); 152 else 153 printf("%d ",dist[i]); 154 } 155 }