Soldier and Traveling
生活随笔
收集整理的這篇文章主要介紹了
Soldier and Traveling
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
http://codeforces.com/contest/546/problem/E
題意:給定一張n個結點,m條邊的無向圖,再給定n個整數a[1],a[2]…a[n]代表初始時每個結點上駐守的士兵數量,每個結點的士兵可以在原地不動,也可以移動到與當前結點鄰接的其他結點上去,但只能移動一次。現在問,能否通過合理的移動使得最終這n個結點駐守的士兵數量分別為b[1],b[2]…b[n],如果可以輸出”YES”,同時輸出一個矩陣表示士兵的移動情況,矩陣的第u行第v列代表有多少個士開始在u結點,后來到了v結點,如果無解輸出”NO”即可。
題解:網絡流
建模,首先建立一個下標為0的源點和下標為n*2+1的匯點,然后把原來圖中的每個結點u拆分成兩個點,u和u+n,然后連接一條(u,u+n,inf)的有向邊,代表士兵可以原地不動,同時把源點到各個點連接一條有向邊(0,u,a[u])代表初始狀態,同時連接各個點到匯點一條有向邊(u,n*2+1,b[u])表示最后的狀態,然后跑最大流算法,如果最大流的值等于數組a的總和和數組b的總和,那就說明問題有解,否則無解。
有個坑點是題目不保證數組a,b的和相同。
/* *@Author: STZG *@Language: C++ */#include<iostream> #include<algorithm> #include<cstdlib> #include<cstring> #include<cstdio> #include<string> #include<vector> #include<bitset> #include<queue> #include<deque> #include<stack> #include<cmath> #include<list> #include<map> #include<set> //#define DEBUG #define RI register int #define endl "\n" using namespace std; typedef long long ll; //typedef __int128 lll; const int N=400+10; const int M=100000+10; const int MOD=1e9+7; const double PI = acos(-1.0); const double EXP = 1E-8; const int INF = 0x3f3f3f3f; int s,t,n,m,k,p,l,r,u,v,w,c2; int ans,cnt,flag,temp,sum; int dis[N],a[N],b[N]; int mp[N][N]; struct node{int u,v,c;node(){};node(int form,int to,int cap):u(form),v(to),c(cap){} }; vector<node>edge; vector<int> G[N]; void Addedge(int u,int v,int cap){edge.push_back({u,v,cap});edge.push_back({v,u,0});int sz=edge.size();G[u].push_back(sz-2);G[v].push_back(sz-1); } bool bfs(int u){memset(dis,-1,sizeof(dis));dis[u]=0;queue<int>q;q.push(u);while(!q.empty()){int u=q.front();q.pop();for(int i=0;i<G[u].size();i++){node e=edge[G[u][i]];//cout<<u<<" "<<e.v<<endl;if(dis[e.v]<0&&e.c>0){dis[e.v]=dis[u]+1;q.push(e.v);}}}return dis[t]>0; } int dfs(int u,int flow){if(u==t)return flow;int now;for(int i=0;i<G[u].size();i++){node e=edge[G[u][i]];if(e.c>0&&dis[u]+1==dis[e.v]&&(now=dfs(e.v,min(flow,e.c)))){edge[G[u][i]].c-=now;edge[G[u][i]^1].c+=now;return now;}}return 0; } void dinic(){while(bfs(s)){int res=0;while(res=dfs(s,INF)){ans+=res;}} } void init(){s=0;t=2*n+1;for(int i=s;i<=t;i++)G[i].clear();edge.clear();ans=0;sum=0; } int main() { #ifdef DEBUGfreopen("input.in", "r", stdin);//freopen("output.out", "w", stdout); #endif//ios::sync_with_stdio(false);//cin.tie(0);//cout.tie(0);//scanf("%d",&t);//int T=0;while(~scanf("%d%d",&n,&m)){init();for(int i=1;i<=n;i++)scanf("%d",&a[i]),sum+=a[i];temp=sum;for(int i=1;i<=n;i++)scanf("%d",&b[i]),sum-=b[i];for(int i=1;i<=n;i++)Addedge(s,i,a[i]);for(int i=1;i<=n;i++)Addedge(i,i+n,INF);for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);Addedge(u,v+n,INF);Addedge(v,u+n,INF);}for(int i=1;i<=n;i++)Addedge(i+n,t,b[i]);if(sum){cout<<"NO"<<endl;continue;}dinic();//cout<<ans<<endl;if(ans==temp){cout<<"YES"<<endl;for(int i=1;i<edge.size();i+=2){if(1+n<=edge[i].u&&edge[i].u<=n*2&&1<=edge[i].v&&edge[i].v<=n&&edge[i].c>0)mp[edge[i].v][edge[i].u-n]=edge[i].c;}for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)printf("%d%c",mp[i][j]," \n"[j==n]);}else{cout<<"NO"<<endl;}}#ifdef DEBUGprintf("Time cost : %lf s\n",(double)clock()/CLOCKS_PER_SEC); #endif//cout << "Hello world!" << endl;return 0; }?
總結
以上是生活随笔為你收集整理的Soldier and Traveling的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Asteroids
- 下一篇: Task Schedule