POJ - 2175 Evacuation Plan(最小费用最大流+消圈定理)
題目鏈接:點擊查看
題目大意:給出n個建筑物和m個避難所,每個建筑物中的人需要到避難所中去避難,規(guī)定花費是建筑物和避難所的曼哈頓距離+1,現(xiàn)在給出一種路線方案,問這個方案是不是最優(yōu)的,如果不是,輸出比當(dāng)前方案更優(yōu)的答案
題目分析:雖然看完題目之后感覺是一道最小費用最大流的題目,但是如果直接照做的話會超時,可能是構(gòu)圖卡SPFA了,其實我們可以換個角度去思考,因為題目并不是要求我們輸出最優(yōu)解,而是更優(yōu)一點的就行,那么我們可以模擬一下整個過程,這個過程叫消圈定理,具體解釋詳見:點我點我
其實就是根據(jù)當(dāng)前方案的流量建立一張費用圖,試著跑一下spfa判斷當(dāng)前圖中是否存在負環(huán),如果存在負環(huán)的話說明替換該負環(huán)上的邊后可以達到更優(yōu)的解,具體建圖方法因為不是真的要求費用流,所以并不需要源點提供流量,但是需要匯點中轉(zhuǎn)流量,建好圖后以匯點為起點跑spfa就好了,算是一個模板題目了,等跑出負環(huán)后再基于負環(huán)操作:
在這里需要注意一下,spfa返回的點并不一定是在負環(huán)上的點,需要我們操作一波將其轉(zhuǎn)移到負環(huán)上的點才能繼續(xù)操作
代碼:
#include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=210;int n,m,cnt,head[N],sum[N],ans[N][N];struct Edge {int to,next,w; }edge[N*N];void addedge(int u,int v,int w) {edge[cnt].to=v;edge[cnt].w=w;edge[cnt].next=head[u];head[u]=cnt++; }struct Pos {int x,y,num;void input(){scanf("%d%d%d",&x,&y,&num);} }a[N];int dis(int x,int y) {return abs(a[x].x-a[y+n].x)+abs(a[x].y-a[y+n].y)+1; }bool vis[N];int d[N],num[N],pre[N];int spfa(int st) {int n=st;memset(pre,-1,sizeof(pre));memset(vis,false,sizeof(vis));memset(d,inf,sizeof(d));memset(num,0,sizeof(num));queue<int>q;d[st]=0;vis[st]=true;num[st]++;q.push(st);while(q.size()){int u=q.front();q.pop();vis[u]=false;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;int w=edge[i].w;if(d[v]>d[u]+w){d[v]=d[u]+w;pre[v]=u;if(!vis[v]){q.push(v);num[v]++;vis[v]=true;if(num[v]>n)return v;}}}}return -1; }void init() {memset(sum,0,sizeof(sum));memset(head,-1,sizeof(head));cnt=0; }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);while(scanf("%d%d",&n,&m)!=EOF){int S=n+m+1;init();for(int i=1;i<=n+m;i++)a[i].input();for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){scanf("%d",&ans[i][j]);addedge(i,j+n,dis(i,j));if(ans[i][j])addedge(j+n,i,-dis(i,j));sum[j]+=ans[i][j];}}for(int i=1;i<=m;i++){if(sum[i]>0)addedge(S,i+n,0);if(sum[i]<a[i+n].num)addedge(i+n,S,0);}int id=spfa(S);if(id==-1)puts("OPTIMAL");else{puts("SUBOPTIMAL");memset(vis,false,sizeof(vis));int v=id;while(!vis[v]){vis[v]=true;v=pre[v];}id=v;do{int u=pre[v];//u->vif(u<=n&&v>n&&v!=S)ans[u][v-n]++;if(v<=n&&u>n&&u!=S)ans[v][u-n]--;v=u;}while(v!=id);for(int i=1;i<=n;i++){for(int j=1;j<=m;j++)printf("%d ",ans[i][j]);printf("\n");}}}return 0; }?
超強干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的POJ - 2175 Evacuation Plan(最小费用最大流+消圈定理)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CodeForces - 1287D N
- 下一篇: UVALive - 3231 Fair