War(最短路+最大流)
阿新 • • 發佈:2018-11-03
War
http://acm.hdu.edu.cn/showproblem.php?pid=3599
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1870 Accepted Submission(s): 442
Yunfeng, the General of the army, must tell how many optimal ship routes are there to the king as soon as possible, or he will be killed. Now he asks for your help. You must help Yunfeng to save his life.
He tells you that there are N island. The islands are numbered from 1 to N(1 is Bangzi and N is Nebir, others are many islands). And there are many ways, each way contain the islands number U and V and the length W. Please output your answer.
Each case contains a number N (N<=1500) means the number of the islands.
And then many lines follow. Each line contains three numbers: U V W (W<10000), means that the distance between island U and V is W. The input of ways are terminated by “ 0 0 0 ”.
Sample Input 1 6 1 2 1 3 2 1 3 4 1 1 3 2 4 2 2 4 5 1 5 6 1 4 6 2 0 0 0 Sample Output 2
Source 2010 ACM-ICPC Multi-University Training Contest(16)——Host by NUDT
1 #include<iostream> 2 #include<cstring> 3 #include<string> 4 #include<cmath> 5 #include<cstdio> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #include<set> 10 #define INF 0x3f3f3f3f 11 #define maxn 2005 12 #define MAXN 1000005 13 #define mem(a,b) memset(a,b,sizeof(a)) 14 using namespace std; 15 16 int n; 17 struct sair{ 18 int len,pos; 19 bool operator<(const sair &b)const{ 20 return len>b.len; 21 } 22 }; 23 int dis[maxn]; 24 int vis[maxn]; 25 vector<pair<int,int> >ve[maxn]; 26 void Dijstra(){ 27 priority_queue<sair>q; 28 sair tmp; 29 tmp.len=0,tmp.pos=1; 30 dis[1]=0; 31 q.push(tmp); 32 while(!q.empty()){ 33 tmp=q.top(); 34 q.pop(); 35 int pos=tmp.pos; 36 if(vis[pos]){ 37 continue; 38 } 39 vis[pos]=1; 40 for(int i=0;i<ve[pos].size();i++){ 41 int f=ve[pos][i].first; 42 int len=ve[pos][i].second; 43 44 if(dis[f]>dis[pos]+len){ 45 dis[f]=dis[pos]+len; 46 tmp.pos=f; 47 tmp.len=dis[f]; 48 q.push(tmp); 49 } 50 } 51 } 52 } 53 54 struct Edge{ 55 int v,next; 56 int cap,flow; 57 }edge[MAXN*5];//注意這裡要開的夠大。。不然WA在這裡真的想罵人。。問題是還不報RE。。 58 int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN]; 59 int cnt=0;//實際儲存總邊數 60 void isap_init() 61 { 62 cnt=0; 63 memset(pre,-1,sizeof(pre)); 64 } 65 void isap_add(int u,int v,int w)//加邊 66 { 67 edge[cnt].v=v; 68 edge[cnt].cap=w; 69 edge[cnt].flow=0; 70 edge[cnt].next=pre[u]; 71 pre[u]=cnt++; 72 } 73 void add(int u,int v,int w){ 74 isap_add(u,v,w); 75 isap_add(v,u,0); 76 } 77 bool bfs(int s,int t)//其實這個bfs可以融合到下面的迭代裡,但是好像是時間要長 78 { 79 memset(dep,-1,sizeof(dep)); 80 memset(gap,0,sizeof(gap)); 81 gap[0]=1; 82 dep[t]=0; 83 queue<int>q; 84 while(!q.empty()) q.pop(); 85 q.push(t);//從匯點開始反向建層次圖 86 while(!q.empty()) 87 { 88 int u=q.front(); 89 q.pop(); 90 for(int i=pre[u];i!=-1;i=edge[i].next) 91 { 92 int v=edge[i].v; 93 if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//注意是從匯點反向bfs,但應該判斷正向弧的餘量 94 { 95 dep[v]=dep[u]+1; 96 gap[dep[v]]++; 97 q.push(v); 98 //if(v==sp)//感覺這兩句優化加了一般沒錯,但是有的題可能會錯,所以還是註釋出來,到時候視情況而定 99 //break; 100 } 101 } 102 } 103 return dep[s]!=-1; 104 } 105 int isap(int s,int t) 106 { 107 if(!bfs(s,t)) 108 return 0; 109 memcpy(cur,pre,sizeof(pre)); 110 //for(int i=1;i<=n;i++) 111 //cout<<"cur "<<cur[i]<<endl; 112 int u=s; 113 path[u]=-1; 114 int ans=0; 115 while(dep[s]<n)//迭代尋找增廣路,n為節點數 116 { 117 if(u==t) 118 { 119 int f=INF; 120 for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增廣路 121 f=min(f,edge[i].cap-edge[i].flow); 122 for(int i=path[u];i!=-1;i=path[edge[i^1].v]) 123 { 124 edge[i].flow+=f; 125 edge[i^1].flow-=f; 126 } 127 ans+=f; 128 u=s; 129 continue; 130 } 131 bool flag=false; 132 int v; 133 for(int i=cur[u];i!=-1;i=edge[i].next) 134 { 135 v=edge[i].v; 136 if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow) 137 { 138 cur[u]=path[v]=i;//當前弧優化 139 flag=true; 140 break; 141 } 142 } 143 if(flag) 144 { 145 u=v; 146 continue; 147 } 148 int x=n; 149 if(!(--gap[dep[u]]))return ans;//gap優化 150 for(int i=pre[u];i!=-1;i=edge[i].next) 151 { 152 if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x) 153 { 154 x=dep[edge[i].v]; 155 cur[u]=i;//常數優化 156 } 157 } 158 dep[u]=x+1; 159 gap[dep[u]]++; 160 if(u!=s)//當前點沒有增廣路則後退一個點 161 u=edge[path[u]^1].v; 162 } 163 return ans; 164 } 165 struct Bian{ 166 int x,y,v; 167 }B[MAXN]; 168 169 int main(){ 170 171 std::ios::sync_with_stdio(false); 172 int T; 173 cin>>T; 174 while(T--){ 175 cin>>n; 176 for(int i=0;i<=n;i++){ 177 dis[i]=INF; 178 vis[i]=0; 179 } 180 for(int i=0;i<=n;i++){ 181 ve[i].clear(); 182 } 183 int a,b,c; 184 int j; 185 int co=0; 186 while(cin>>B[co].x>>B[co].y>>B[co].v){ 187 if(!B[co].x&&!B[co].y&&!B[co].v){ 188 break; 189 } 190 ve[B[co].x].push_back(make_pair(B[co].y,B[co].v)); 191 ve[B[co].y].push_back(make_pair(B[co].x,B[co].v)); 192 co++; 193 } 194 Dijstra(); 195 isap_init(); 196 if(dis[n]==INF||n==1){ 197 cout<<0<<endl; 198 continue; 199 } 200 for(int i=0;i<co;i++){///判斷是不是最短路上的邊 201 if(dis[B[i].x]-dis[B[i].y]==B[i].v){ 202 add(B[i].y,B[i].x,1); 203 } 204 else if(dis[B[i].y]-dis[B[i].x]==B[i].v){ 205 add(B[i].x,B[i].y,1); 206 } 207 } 208 int s=1,t=n; 209 int ans=isap(s,t); 210 cout<<ans<<endl; 211 } 212 213 }View Code