参考自:http://www.bubuko.com/infodetail-1762450.html
题目大意:给你一副无向图,边有权值,初始权值>=0,若权值==0,则需要把它变为一个正整数(不超过1e18),现在问你有没有一种方法,
使图中的边权值都变为正整数的时候,从 S 到 T 的最短路恰好等于 L。
若没有输出 "NO",否则输出 "YES",同时输出新图中的所有边权值。
题解:显然将所有边值都设为1若最短路大于L则无解,所有边值设为INF最短路小于L则无解。
其他情况一定是有解的。可以想象成将所有的边一次加一,如此循环操作,最短路必定会慢慢加一必定能够到达L;
那么假设总共有x条权值不确定的边,假设先对第一条边操作,将其不断加一,每加一次跑一遍最短路,始终不能到达L则说明经过第一条边的路必定始终大于L,同理对接下来的边也如此操作。当然这样直接写会很复杂,可以用二分来模拟这个过程,具体就是代码中的cek()函数
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 #include <map> 7 #include <vector> 8 #include <queue> 9 using namespace std; 10 #define EPS 1e-10 11 typedef long long ll; 12 const int maxn = 1e4 + 10; 13 const double INF = 1e9 +1.0; 14 int n,m,l,s,t,cnt; 15 int head[1010]; 16 double dis[1010],gra[1010][1010]; 17 vector<pair<int,int> >q; 18 vector<int>q1; 19 struct st1{ 20 int to,nxt,u; 21 double w; 22 }edge[maxn*2]; 23 void add(int u,int v,double w){ 24 edge[cnt].u = u; 25 edge[cnt].to = v; 26 edge[cnt].w = w; 27 edge[cnt].nxt = head[u]; 28 cnt++; 29 } 30 int dijstra() 31 { 32 int i,j,pos=1; 33 double min; 34 int visit[1010]; 35 memset(visit,0,sizeof(visit)); 36 double inf = 1e15+1.0; 37 for(i=0;i<n;++i) 38 dis[i]= gra[s][i]; 39 visit[s]=1; 40 dis[s]=0; 41 for(i=0;i<n;i++) 42 { 43 min=inf; 44 for(j=0;j<n;++j) 45 { 46 if(!visit[j]&&min>dis[j]) 47 { 48 min=dis[j]; 49 pos=j; 50 } 51 } 52 visit[pos]=1; 53 for(j=0;j<n;++j) 54 { 55 if(!visit[j]&&dis[j]>dis[pos]+gra[pos][j]){ 56 dis[j]=dis[pos]+gra[pos][j]; 57 58 } 59 } 60 } 61 //cout<<dis[t]<<endl; 62 return dis[t]; 63 64 } 65 int cek(ll sum){ 66 for(int i = 0;i < q.size();i++){ 67 int u = q[i].first,v = q[i].second; 68 gra[u][v] = gra[v][u] = 1 + min(sum,1000000000ll); 69 int x = q1[i]; 70 edge[x].w = gra[u][v]; 71 edge[x+1].w = gra[u][v]; 72 sum -= gra[u][v] - 1; 73 } 74 return dijstra(); 75 } 76 int main(){ 77 // freopen("in.txt","r",stdin); 78 memset(head,-1,sizeof(head)); 79 scanf("%d%d%d%d%d",&n,&m,&l,&s,&t); 80 int a,b; 81 double c; 82 for(int i = 0;i < n;i++) 83 for(int j = i; j < n;j++){ 84 gra[i][j] = INF; 85 gra[j][i] = INF; 86 } 87 for(int i = 1;i <= m;i++){ 88 scanf("%d%d%lf",&a,&b,&c); 89 if(c == 0){ 90 q.push_back(make_pair(a,b)); 91 q1.push_back(cnt); 92 } 93 else{ 94 gra[a][b] = gra[b][a] = c; 95 } 96 add(a,b,c); 97 add(b,a,c); 98 } 99 ll L = 0,r =(ll)q.size()*1e9; 100 if(cek(L) > l||cek(r) < l){ 101 // cout<<cek(L)<<" "<<cek(r)<<" "<<l<<endl; 102 cout<<"NO"<<endl; 103 return 0; 104 } 105 while(L <= r){ 106 ll mid = (L + r)/2; 107 int temp = cek(mid); 108 if(temp > l) r = mid; 109 else if(temp < l) L = mid + 1; 110 else break; 111 } 112 cout<<"YES"<<endl; 113 for(int i = 0;i <= 2*m - 2;i += 2) 114 printf("%d %d %0.f ",edge[i].u,edge[i].to,edge[i].w); 115 return 0; 116 }