续。。。。。TAT这回不到50题编辑器就崩了。。
这里塞40道吧= =
bzoj 1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害
比较经典的最小割?。。然而一开始还是不会QAQ
和地震伤害1的区别在于这题求的是最少的损坏牧场数目。把牧场拆点,因为要让1和被报告的点不联通,把1归到S集,被报告的点归到T集,就变成求最小割了。
具体建图:
假设点拆成x和x’,x和x‘间连边(就是等下要割的)。被报告的点和1点:容量无穷大(不能割);其他点容量为1。
原图中相连的边就按照二分图正常姿势,出点连到入点,容量无穷大(路没坏)。
最后就是s连1,被报告的点连t,容量都无穷大
dinic大法好。。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn=3003; 6 const int inf=1023333333; 7 struct zs{ 8 int too,pre,flow; 9 }e[98233]; 10 int last[maxn<<1],dl[maxn<<1],l,r,now,tot=1; 11 short dis[maxn<<1]; 12 bool u[maxn]; 13 int i,j,k,n,m,a,b,s,t,p,ans; 14 15 int ra;char rx; 16 inline int read(){ 17 rx=getchar();ra=0; 18 while(rx<'0'||rx>'9')rx=getchar(); 19 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 20 } 21 inline void insert(int a,int b,int c){ 22 // printf(" %d-->%d %d\n",a,b,c==1?1:233); 23 e[++tot].too=b;e[tot].flow=c;e[tot].pre=last[a];last[a]=tot; 24 e[++tot].too=a;e[tot].flow=0;e[tot].pre=last[b];last[b]=tot; 25 } 26 inline bool bfs(){ 27 memset(dis,255,(t+1)<<1); 28 l=0;r=1;dl[1]=s;dis[s]=0; 29 while(l<r&&dis[t]==-1)for(now=dl[++l],i=last[now];i;i=e[i].pre)if(e[i].flow&&dis[e[i].too]==-1) 30 dis[e[i].too]=dis[now]+1,dl[++r]=e[i].too; 31 // for(i=1;i<=t;i++)printf(" %d %d\n",i,dis[i]); 32 return dis[t]!=-1; 33 } 34 int dfs(int x,int mx){ 35 if(x==t||!mx)return mx; 36 int used=0,i,w; 37 for(i=last[x];i;i=e[i].pre)if(dis[e[i].too]==dis[x]+1&&e[i].flow){ 38 w=dfs(e[i].too,min(mx-used,e[i].flow));if(w){ 39 e[i].flow-=w;e[i^1].flow+=w; 40 used+=w;if(used==mx)return mx; 41 } 42 } 43 dis[x]=-1;return used; 44 } 45 int main(){ 46 n=read();m=read();p=read();s=0;t=n+n+1; 47 for(i=1;i<=m;i++)a=read(),b=read(),insert(a+n,b,inf),insert(b+n,a,inf); 48 for(i=1;i<=p;i++)a=read(),u[a]=1,insert(a,a+n,inf),insert(a+n,t,inf); 49 for(i=2;i<=n;i++)if(!u[i])insert(i,i+n,1);if(!u[1])insert(1,1+n,inf); 50 insert(s,1,inf); 51 while(bfs())ans+=dfs(s,inf); 52 printf("%d\n",ans); 53 return 0; 54 } 55 56 View