Soldier and Traveling
http://codeforces.com/contest/546/problem/E
題意:給定一張n個(gè)結(jié)點(diǎn),m條邊的無向圖,再給定n個(gè)整數(shù)a[1],a[2]…a[n]代表初始時(shí)每個(gè)結(jié)點(diǎn)上駐守的士兵數(shù)量,每個(gè)結(jié)點(diǎn)的士兵可以在原地不動(dòng),也可以移動(dòng)到與當(dāng)前結(jié)點(diǎn)鄰接的其他結(jié)點(diǎn)上去,但只能移動(dòng)一次。現(xiàn)在問,能否通過合理的移動(dòng)使得最終這n個(gè)結(jié)點(diǎn)駐守的士兵數(shù)量分別為b[1],b[2]…b[n],如果可以輸出”YES”,同時(shí)輸出一個(gè)矩陣表示士兵的移動(dòng)情況,矩陣的第u行第v列代表有多少個(gè)士開始在u結(jié)點(diǎn),后來到了v結(jié)點(diǎn),如果無解輸出”NO”即可。
題解:網(wǎng)絡(luò)流
建模,首先建立一個(gè)下標(biāo)為0的源點(diǎn)和下標(biāo)為n*2+1的匯點(diǎn),然后把原來圖中的每個(gè)結(jié)點(diǎn)u拆分成兩個(gè)點(diǎn),u和u+n,然后連接一條(u,u+n,inf)的有向邊,代表士兵可以原地不動(dòng),同時(shí)把源點(diǎn)到各個(gè)點(diǎn)連接一條有向邊(0,u,a[u])代表初始狀態(tài),同時(shí)連接各個(gè)點(diǎn)到匯點(diǎn)一條有向邊(u,n*2+1,b[u])表示最后的狀態(tài),然后跑最大流算法,如果最大流的值等于數(shù)組a的總和和數(shù)組b的總和,那就說明問題有解,否則無解。
有個(gè)坑點(diǎn)是題目不保證數(shù)組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; }?
總結(jié)
以上是生活随笔為你收集整理的Soldier and Traveling的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Asteroids
- 下一篇: Task Schedule