Uva 1660:Cable TV Network

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=51254

题目大意

给定一个n个结点的无向图(n<=50),求最少删除几个结点能使这个图不连通。

分析

由“连通”不难想到最小割,但这里求的是结点的”最小割“,似乎传统做法并不可行?非也,还是用传统的算法,只不过要用到”结点容量“的办法,把一个点拆成两个,中间连一条容量为1的边,其他边容量无限,具体原理如下图:

这里写图片描述

原图可转化为(x为限定的”结点容量“):

这里写图片描述

这样选定一个源点,枚举汇点用最大流即可。


代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

#define rep(i,x,y) for (int i=x;i<=y;i++)
#define dep(i,y,x) for (int i=y;i>=x;i--)
#define read(x) scanf("%d",&x)

using namespace std;

const int maxn=200+23,INF=(1<<23);

struct Edge{
  int from,to,flow,cap;
  Edge(int x1,int x2,int x3,int x4):from(x1),to(x2),flow(x3),cap(x4) {}
};

char s[maxn];


int n,m,M,ans,k,u,v,a[maxn],p[maxn];

bool d[maxn][maxn];

vector<Edge> E;
vector<int> G[maxn];

void addadge(int u,int v,int c)
{
 E.push_back(Edge(u,v,0,c));
 E.push_back(Edge(v,u,0,0));
 M=E.size();
 G[u].push_back(M-2);
 G[v].push_back(M-1);
}

int Maxflow(int S,int T)
{
 rep(i,0,E.size()-1) E[i].flow=0;
 int flow=0;
 bool mark=1;
 while (1)
 {
  memset(a,0,sizeof(a));
  a[S]=INF;
  queue<int> Q;
  Q.push(S);
  while (!Q.empty())
  {
   int x=Q.front(),len=G[x].size();Q.pop();
   rep(i,0,len-1)
   {
    Edge& Ed=E[G[x][i]];
    if (!a[Ed.to] && (Ed.cap>Ed.flow))
    {
     a[Ed.to]=min(a[x],Ed.cap-Ed.flow);
     Q.push(Ed.to);
     p[Ed.to]=G[x][i];
    }
   }
   if (a[T]) break;
  }
  
  if ((mark) && (!a[T])) return -1; else mark=0;

  if (!a[T]) break;

  for (int i=T;i!=S;i=E[p[i]].from)
  {
   E[p[i]].flow+=a[T];
   E[p[i]^1].flow-=a[T];
  }

  flow+=a[T];
 }
 return flow;
}

bool special_judge()
{
 rep(i,0,n-1)
  rep(j,0,n-1) 
   if ((i!=j) && (!d[i][j])) return 0;
 return 1;
}

int main()
{
 while ((scanf("%d%d",&n,&m)==2))
 {
  memset(d,0,sizeof(d));
  
  rep(i,0,maxn-1) G[i].clear();
  E.clear();
  rep(i,0,n-1) {addadge(i,i+n,1);addadge(i+n,i,1);} //连拆点之间的边
  rep(i,1,m) 
  {
   scanf(" (%d,%d)",&u,&v);  //注意scanf的用法!
   addadge(u,v+n,INF); 
   addadge(v,u+n,INF);
   d[u][v]=d[v][u]=1;
 }
 
 if (special_judge()) {printf("%d\n",n);continue;} //如果是完全图则全删掉
 
 ans=INF;
  rep(j,1,n-1)
    if (!d[0][j]) 
    { 
      k=Maxflow(0,j+n);
      if (k==-1) {ans=0;break;} //原图不联通
    ans=min(k,ans);
 }

 printf("%d\n",ans>=(n-1)?n:ans);  
 }
 return 0;
}

posted @ 2016-03-05 18:28  Krew  阅读(244)  评论(0)    收藏  举报