方法一
这道题的题意真的难理解,想了很久都没懂什么叫最小值最大......
读完题一定要看样例!
题目可以理解为:有甲要走最短路,乙在甲走到某一顶点v时可以删去一条v----->u的边,两人博弈,甲走的路最短为多少?
分析一下数据范围可以发现n≤100,m≤500,O(n³)的算法都可以过
我们可以先预处理出对于每一顶点V,当甲走到V时,乙去掉一条V的出边,此时甲从V到2的最短路长,记为bad[v]
dp[v]为v的子图中删去一条边甲可以走的最短路
①删去一条v的出边
②删去v的子图中的其它出边
所以dp[v]=max{bad[v],min{dp[u]+cost(u,v)|v到u有边} }
可以通过最短路转移
复杂度O(n log n)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define F first 4 #define S second 5 struct WarTransportation 6 { 7 vector<pair<int,int> >nei[105],nei2[105]; 8 int bad[105]; 9 bool vis[105]; 10 int dijdis[105],n; 11 int dij(int st,int cant) 12 { 13 for(int i=0;i<104;i++) dijdis[i]=1e9; 14 memset(vis,0,sizeof vis); 15 dijdis[st]=0; 16 priority_queue<pair<int,int> > q; 17 q.push(make_pair(0,st)); 18 while(!q.empty()) 19 { 20 pair<int,int> tmp=q.top(); 21 q.pop(); 22 if(vis[tmp.S]) continue; 23 tmp.F=-tmp.F; 24 int v=tmp.S; 25 vis[v]=1; 26 if(tmp.S==1) return dijdis[1]; 27 for(int i=0;i<nei[v].size();i++) 28 { 29 if(v==st&&i==cant) continue; 30 int u=nei[v][i].F,cost=dijdis[v]+nei[v][i].S; 31 if(cost>=dijdis[u]) continue; 32 dijdis[u]=cost; 33 q.push(make_pair(-cost,u)); 34 } 35 } 36 //这里要返回inf 37 return 1e9; 38 } 39 void getbad() 40 { 41 for(int i=0;i<n;i++) 42 { 43 int fir=0; 44 for(int j=0;j<nei[i].size();j++) 45 { 46 int x=dij(i,j); 47 if(x>fir) fir=x; 48 } 49 bad[i]=fir; 50 } 51 } 52 int dp[105]; 53 int messenger(int yy,vector<string> v) 54 { 55 n=yy; 56 int m; 57 stringstream ss; 58 //要熟悉stringstream的用法! 59 for(int i=0;i<v.size();i++) 60 { 61 ss<<v[i]; 62 }int x,y,co; 63 for(;ss>>x>>y>>co;) 64 { 65 m++; 66 x--;y--; 67 nei[x].push_back(make_pair(y,co)); 68 nei2[y].push_back(make_pair(x,co)); 69 char c; 70 ss>>c; 71 } 72 getbad(); 73 memset(dp,-1,sizeof dp); 74 priority_queue<pair<int,int> >q; 75 q.push(make_pair(-bad[1],1)); 76 for(int i=0;i<104;i++)dp[i]=2e9; 77 dp[1]=0; 78 memset(vis,0,sizeof vis); 79 while(!q.empty()) 80 { 81 pair<int,int>tmp=q.top(); 82 q.pop(); 83 if(vis[tmp.S]) continue; 84 int v=tmp.S; 85 vis[v]=1; 86 for(int i=0;i<nei2[v].size();i++) 87 { 88 int u=nei2[v][i].F,cost=max(bad[u],nei2[v][i].S+dp[v]); 89 if(cost>=dp[u]) continue; 90 dp[u]=cost; 91 q.push(make_pair(-cost,u)); 92 } 93 } 94 return (dp[0]<1e9)?dp[0]:-1; 95 } 96 };
方法二
要使最小值最大,我们也可以考虑二分答案。
可以二分在最坏情况下,最短路能不能小于T
直接跑最短路,能够转移的条件为dist[v]+cost(v,u)+bad[u]<=T&&dist[v]+cost(v,u)<dist[u]
复杂度O(n log2 n)
1 typedef int vert; 2 typedef int cost; 3 typedef pair<cost,vert> edge; 4 typedef vector<edge> edges; 5 typedef vector<edges> graph; 6 7 static const cost INF = 0x12345678; // large enough but INF+INF<2^31 8 static const vert START = 0; 9 static const vert GOAL = 1; 10 11 class WarTransportation { public: 12 int messenger(int n, vector <string> highways) 13 { 14 return solve( parse(n, highways) ); 15 } 16 17 graph parse(int n, vector <string> highways) 18 { 19 graph G(n); 20 21 string hi = accumulate(highways.begin(), highways.end(), string()); 22 for(int i=0; i<hi.size(); ) 23 { 24 int k = hi.find(',', i); 25 if( k == string::npos ) k = hi.size(); 26 27 int a, b, c; 28 stringstream(hi.substr(i,k-i)) >> a >> b >> c; 29 G[a-1].push_back( edge(c,b-1) ); 30 31 i = k+1; 32 } 33 34 return G; 35 } 36 37 int solve( const graph& G ) 38 { 39 // Suppose you reached the city "v", and found there the most critical load is broken. 40 // How long will it take a detour to the GOAL? It's ukai[v]! 41 42 vector<cost> ukai; 43 for(int v=0; v<G.size(); ++v) 44 ukai.push_back( ukaiDist(G,v) ); 45 46 // Compute the least T such that: 47 // we get to the GOAL, making the worst case time <= T? 48 49 cost L=0, R=99999999; 50 if( !reachable(G, ukai, R) ) return -1; 51 if( reachable(G, ukai, L) ) return 0; 52 53 // We can when T=R, and cannot T=L. 54 // That is, T in (L, R]. Now let's binary-search! 55 56 while( R-L>1 ) 57 (reachable(G, ukai, (L+R)/2) ? R : L) = (L+R)/2; 58 return R; 59 } 60 61 cost ukaiDist( const graph& G, vert v ) 62 { 63 if( v == GOAL ) return 0; 64 if( G[v].size() == 0 ) return INF; 65 66 cost worst = 0; 67 for(int f=0; f<G[v].size(); ++f) // f : broken road 68 { 69 priority_queue< edge, vector<edge>, greater<edge> > Q; 70 set<vert> V; 71 V.insert(v); 72 for(int i=0; i<G[v].size(); ++i) // push all loads from v, except f 73 if( i != f ) 74 Q.push( G[v][i] ); 75 worst = max( worst, dijkstra(G,Q,V) ); // start dijkstraing 76 } 77 return worst; 78 } 79 80 81 bool reachable( const graph& G, const vector<cost>& ukai, cost ukaiLimit ) 82 { 83 priority_queue< edge, vector<edge>, greater<edge> > Q; 84 set<vert> V; 85 Q.push( edge(0,START) ); 86 return dijkstra(G, Q, V, ukai, ukaiLimit) != INF; 87 } 88 89 cost dijkstra( const graph& G, 90 priority_queue< edge, vector<edge>, greater<edge> >& Q, set<vert>& V, 91 const vector<cost>& ukai=vector<cost>(), cost ukaiLimit=-1 92 ) { 93 while( !Q.empty() ) 94 { 95 // pop 96 cost c = Q.top().first; 97 vert v = Q.top().second; 98 Q.pop(); 99 100 // check 101 if( V.count(v) || (ukaiLimit>=0 && c+ukai[v]>ukaiLimit) ) 102 continue; 103 if( v == GOAL ) 104 return c; 105 V.insert(v); 106 107 // next 108 for(int i=0; i<G[v].size(); ++i) 109 if( !V.count(G[v][i].second) ) 110 Q.push( edge(c+G[v][i].first, G[v][i].second) ); 111 } 112 return INF; 113 } 114 };