n<=3000个点m<=20000条无向边的图,有p<=n个出发点,每个出发点都不可拆,现拆一些点使每个出发点都不能到达点1,求最小点数。
简单的最小割。每个点拆成两个x和y,无向边A--B即Ay->Bx,By->Ax,每个点拆成的x和y再连边容量1,然后建超级源向p个点连边,最大流,没了。
错误。没看题。p个点不可割。WA了一发。正确做法只要把p个点的x->y的边容量设inf即可。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<math.h> 6 //#include<iostream> 7 using namespace std; 8 9 int n,m,p; 10 #define maxn 6011 11 #define maxm 100011 12 const int inf=0x3f3f3f3f; 13 struct Network 14 { 15 struct Edge{int to,next,cap,flow;}edge[maxm]; 16 int first[maxn],le,n; 17 void clear(int n) 18 { 19 memset(first,0,sizeof(first)); 20 le=2;this->n=n; 21 } 22 void in(int x,int y,int cap) 23 { 24 Edge &e=edge[le]; 25 e.to=y;e.cap=cap;e.flow=0; 26 e.next=first[x];first[x]=le++; 27 } 28 void insert(int x,int y,int cap) 29 { 30 in(x,y,cap); 31 in(y,x,0); 32 } 33 int s,t,que[maxn],head,tail,dis[maxn],cur[maxn]; 34 bool bfs() 35 { 36 memset(dis,0,sizeof(dis)); 37 dis[s]=1; 38 que[head=(tail=1)-1]=s; 39 while (head!=tail) 40 { 41 const int now=que[head++]; 42 for (int i=first[now];i;i=edge[i].next) 43 { 44 Edge &e=edge[i]; 45 if (e.cap>e.flow && !dis[e.to]) 46 { 47 dis[e.to]=dis[now]+1; 48 que[tail++]=e.to; 49 } 50 } 51 } 52 return dis[t]; 53 } 54 int dfs(int x,int a) 55 { 56 if (x==t || !a) return a; 57 int flow=0,f; 58 for (int &i=cur[x];i;i=edge[i].next) 59 { 60 Edge &e=edge[i]; 61 if (dis[e.to]==dis[x]+1 && (f=dfs(e.to,min(a,e.cap-e.flow)))>0) 62 { 63 e.flow+=f; 64 edge[i^1].flow-=f; 65 flow+=f; 66 a-=f; 67 if (!a) break; 68 } 69 } 70 return flow; 71 } 72 int Dinic(int s,int t) 73 { 74 this->s=s,this->t=t; 75 int flow=0; 76 while (bfs()) 77 { 78 for (int i=1;i<=n;i++) cur[i]=first[i]; 79 flow+=dfs(s,0x3f3f3f3f); 80 } 81 return flow; 82 } 83 }g; 84 int x,y;int vis[maxn]; 85 int main() 86 { 87 scanf("%d%d%d",&n,&m,&p); 88 g.n=(n<<1)^1;int s=g.n,t=1; 89 for (int i=1;i<=m;i++) 90 { 91 scanf("%d%d",&x,&y); 92 g.insert(x+n,y,inf); 93 g.insert(y+n,x,inf); 94 } 95 memset(vis,0,sizeof(vis)); 96 for (int i=1;i<=p;i++) 97 { 98 scanf("%d",&x);vis[x]=1; 99 g.insert(s,x,inf); 100 } 101 for (int i=1;i<=n;i++) if (!vis[i]) g.insert(i,i+n,1);else g.insert(i,i+n,inf); 102 printf("%d\n",g.Dinic(s,t)); 103 return 0; 104 }
时间: 2024-11-12 13:12:56