1779: [Usaco2010 Hol]Cowwar 奶牛战争
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 302 Solved: 131
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
TEJTJ
1 2
2 3
3 4
4 5
Sample Output
HINT
输出细节:
其他可行的输出为:
2
MOVE 3 2
ATTACK 5 4
ATTACK 2 1
或者
2
ATTACK 5 4
MOVE 3 2
ATTACK 2 1
其它的输出祇是改变一下命令的顺序。但是并不是所有的数据都是这样的。
Source
一只$T$牛挂一次,一只$J$牛搞一头$T$,这可以用网络流瞎搞(设$s,t$为源汇点)
看这个$E$,显然只能走一次,于是拆成$E_1,E_2$,$link(E_1,E_2,1)$
牛可能从$E$攻击$T$,$link(E_2,T,1)$
看这个$T$,显然只能挂一次,$link(T,t,1)$
看这个$J$,一大堆操作可以搞,我们也把它拆成$J_1,J_2$
但是!两个点似乎不顶用,比如说本人花了1.5h造了个数据卡了自己的两点图:
8 7
JJJEETTT
1 2
3 2
2 4
2 7
2 5
4 6
5 8
大概长这样:
$J_1,J_2$不够用,那么把$J$拆成$J_1,J_2,J_3$
$link(s,J_1,1),link(J_1,J_2,1)$
$J_1$是原来的点,$J_2$表示从其他$J$转移过来的点
$J_3$连$T$,显然只能一个$J$连$T$,$link(J_2,J_3,1)$
设这个$J$点的编号为$i$,枚举$j$
$if(q[j]=='E') link(i,j,1)$
$if(q[j]=='J') link(i,j_2,1)$
$if(q[j]=='T') link(i_3,j,1);$
蓝后就可以快乐地跑最大流辣
#include<iostream> #include<cstdio> #include<cstring> #include<queue> using namespace std; #define N 5005 #define M 100005 const int inf=2e9; int n,m,S,T,d[N],cur[N]; char q[N]; queue <int> h; bool vis[N],e[N][N]; int cnt=1,hd[N],nxt[M],ed[N],poi[M],val[M]; inline void adde(int x,int y,int v){ nxt[ed[x]]=++cnt, hd[x]=hd[x]?hd[x]:cnt, ed[x]=cnt, poi[cnt]=y, val[cnt]=v; } inline void link(int x,int y,int v){adde(x,y,v),adde(y,x,0);} bool bfs(){ for(int i=1;i<=T;++i) vis[i]=0,cur[i]=hd[i]; h.push(S); vis[S]=1; while(!h.empty()){ int x=h.front(); h.pop(); for(int i=hd[x];i;i=nxt[i]){ int to=poi[i]; if(!vis[to]&&val[i]>0) vis[to]=1,d[to]=d[x]+1,h.push(to); } }return vis[T]; } int dfs(int x,int a){ if(x==T||a==0) return a; int F=0,f; for(int &i=cur[x];i;i=nxt[i]){ int to=poi[i]; if(d[to]==d[x]+1&&(f=dfs(to,min(a,val[i])))>0) a-=f,F+=f,val[i]-=f,val[i^1]+=f; if(!a) break; }return F; } int dinic(){int re=0; while(bfs())re+=dfs(S,inf); return re;} int main(){ scanf("%d%d",&n,&m); scanf("%s",q+1); S=n*3+1; T=S+1;//开3*n的点 for(int i=1,u,v;i<=m;++i) scanf("%d%d",&u,&v),e[u][v]=e[v][u]=1; for(int i=1;i<=n;++i){ if(q[i]=='T') link(i,T,1); if(q[i]=='E'){ link(i,i+n,1); for(int j=1;j<=n;++j) if(e[i][j]&&q[j]=='T') link(i+n,j,1); } if(q[i]=='J'){ link(S,i,1); link(i,i+n,1); link(i+n,i+n+n,1); for(int j=1;j<=n;++j){ if(!e[i][j]) continue; if(q[j]=='E') link(i,j,1); if(q[j]=='J') link(i,j+n,1); if(q[j]=='T') link(i+n+n,j,1); } } }printf("%d",dinic()); return 0; }