UVA 1660 Cable TV Network 电视网络(无向图,点连通度,最大流)

题意:给一个无向图,求其点连通度?(注意输入问题)

思路:

  如果只有1个点,那么输出“1”;

  如果有0条边,那么输出“0”;

  其他情况:用最大流解决。下面讲如何建图:

  图的连通度问题是指:在图中删去部分元素(点或边),使得图中指定的两个点s和t不连通(即不存在从s到t的路径),求至少要删去几个元素。

  图的连通度分为点连通度和边连通度:
    (1)点连通度:只许删点,求至少要删掉几个点(当然,s和t不能删去,这里保证原图中至少有三个点);
    (2)边连通度:只许删边,求至少要删掉几条边。

  并且,有向图和无向图的点连通度求法不同,因此还要分开考虑。说明:最大流对应的是最小割。

  【有向图】:这个其实就是最小割问题。以s为源点,t为汇点建立网络,原图中的每条边在网络中仍存在,容量为1。

  【无向图】:需要拆点,每个点都拆成两个点v和v‘,并连1条有向边v->v‘,容量为1。点v承接原图中所有入边,点v‘承接原图中所有出边。那么对于原图每条有向边就得建两条边了,容量无穷,且涉4个新顶点。

  【混合图】无向边按无向图处理,有向边按有向图处理。

  最后,源点S到汇点,跑一次最大流,就得到了答案。如果无指定ST,那么应该顶下1个S,再穷举其他点作为T。这个S应该如何定就不知道了,时间充裕就穷举S和T,不充裕就找个度最少的为S。

  针对此题,随意定个0号点为源点也能过,当然穷举两点也能过。

  

  1 #include <bits/stdc++.h>
  2 #define LL long long
  3 #define pii pair<int,int>
  4 #define INF 0x7f7f7f7f
  5 using namespace std;
  6 const int N=110;
  7 int n, m, edge_cnt;
  8 vector<int> vect[N*2];
  9 int path[N], flow[N];
 10
 11 struct node
 12 {
 13     int from, to, cap, flow;
 14     node(){};
 15     node(int f,int t,int c,int fl):from(f),to(t),cap(c),flow(fl){};
 16 }edge[50000], cpy[50000];
 17
 18 void add_node(int from, int to, int cap, int flow)
 19 {
 20     edge[edge_cnt]=node(from,to,cap,flow);
 21     vect[from].push_back(edge_cnt++);
 22 }
 23
 24 int BFS(int s,int e)
 25 {
 26     deque<int> que(1,s);
 27     flow[s]=INF;
 28
 29     while(!que.empty())
 30     {
 31         int x=que.front();
 32         que.pop_front();
 33         for(int i=0; i<vect[x].size(); i++)
 34         {
 35             node e=cpy[vect[x][i]];
 36             if(!flow[e.to] && e.cap>e.flow )
 37             {
 38                 flow[e.to]=min(flow[e.from],e.cap-e.flow);
 39                 path[e.to]=vect[x][i];
 40                 que.push_back(e.to);
 41             }
 42         }
 43         if(flow[e]) break;
 44     }
 45     return flow[e];
 46 }
 47
 48 int max_flow(int s,int e)
 49 {
 50     int ans_flow=0;
 51     while(true)
 52     {
 53         memset(path,0,sizeof(path));
 54         memset(flow,0,sizeof(flow));
 55
 56         int tmp=BFS(s,e);
 57         if(!tmp)    return ans_flow;
 58         ans_flow+=tmp;
 59
 60         int ed=e;
 61         while(ed!=s)
 62         {
 63             int t=path[ed];
 64             cpy[t].flow+=tmp;
 65             cpy[t^1].flow-=tmp;
 66             ed=cpy[t].from;
 67         }
 68     }
 69 }
 70
 71 int cal()
 72 {
 73     int ans=INF;
 74
 75     for(int i=0; i<edge_cnt; i++)
 76     {
 77         if( edge[i].from==0 && edge[i].to==1 && edge[i].cap>0 )
 78         {
 79             edge[i].cap=INF;
 80             break;
 81         }
 82     }
 83     for(int k=1; k<n; k++)  //枚举汇点
 84     {
 85         memcpy(cpy, edge, sizeof(edge));
 86         for(int i=0; i<edge_cnt; i++)   //所有边
 87         {
 88             if( cpy[i].from==k*2 && cpy[i].to==k*2+1 &&cpy[i].cap>0 )
 89             {
 90                 cpy[i].cap=INF;
 91                 break;
 92             }
 93         }
 94         ans=min(ans, max_flow(0,k*2+1));
 95     }
 96     return ans==INF?n:ans;
 97 }
 98
 99
100 int main()
101 {
102     freopen("input.txt", "r", stdin);
103     int a, b;
104     char c;
105     while(cin>>n>>m)
106     {
107         edge_cnt=0;
108         memset(edge,0,sizeof(edge));
109         for(int i=n*2; i>=0; i--) vect[i].clear();
110
111         for(int i=0; i<n; i++)  //拆点
112         {
113             add_node(i*2, i*2+1, 1, 0);
114             add_node(i*2+1, i*2, 0, 0);
115         }
116
117         for(int i=0; i<m; i++)
118         {
119             while(c=getchar(), c!=‘(‘ );
120             scanf("%d%c%d%c",&a,&c,&b,&c);
121
122             add_node(a*2+1, b*2, INF, 0 );  //每条无向边拆2条有向
123             add_node(b*2, a*2+1, 0, 0 );
124
125             add_node(b*2+1, a*2, INF, 0);
126             add_node(a*2, b*2+1, 0, 0);
127         }
128         printf("%d\n",cal());
129     }
130     return 0;
131 }

AC代码(任意源)

#include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=110;
int n, m, edge_cnt;
vector<int> vect[N*2];
int path[N], flow[N];

struct node
{
    int from, to, cap, flow;
    node(){};
    node(int f,int t,int c,int fl):from(f),to(t),cap(c),flow(fl){};
}edge[50000], cpy[50000], old[50000];

void add_node(int from, int to, int cap, int flow)
{
    edge[edge_cnt]=node(from,to,cap,flow);
    vect[from].push_back(edge_cnt++);
}

int BFS(int s,int e)
{
    deque<int> que(1,s);
    flow[s]=INF;

    while(!que.empty())
    {
        int x=que.front();
        que.pop_front();
        for(int i=0; i<vect[x].size(); i++)
        {
            node e=cpy[vect[x][i]];
            if(!flow[e.to] && e.cap>e.flow )
            {
                flow[e.to]=min(flow[e.from],e.cap-e.flow);
                path[e.to]=vect[x][i];
                que.push_back(e.to);
            }
        }
        if(flow[e]) break;
    }
    return flow[e];
}

int max_flow(int s,int e)
{
    int ans_flow=0;
    while(true)
    {
        memset(path,0,sizeof(path));
        memset(flow,0,sizeof(flow));

        int tmp=BFS(s,e);
        if(!tmp)    return ans_flow;
        ans_flow+=tmp;

        int ed=e;
        while(ed!=s)
        {
            int t=path[ed];
            cpy[t].flow+=tmp;
            cpy[t^1].flow-=tmp;
            ed=cpy[t].from;
        }
    }
}

int cal()
{
    int ans=INF;
    for(int s=0; s<n; s++)  //枚举源点
    {
        memcpy(old, edge, sizeof(edge));
        for(int i=0; i<edge_cnt; i++)
        {
            if( old[i].from==s*2 && old[i].to==s*2+1 && old[i].cap>0 )
            {
                old[i].cap=INF;
                break;
            }
        }

        for(int k=s+1; k<n; k++)  //枚举汇点
        {
            memcpy(cpy, old, sizeof(old));
            for(int i=0; i<edge_cnt; i++)   //所有边
            {
                if( cpy[i].from==k*2 && cpy[i].to==k*2+1 &&cpy[i].cap>0 )
                {
                    cpy[i].cap=INF;
                    break;
                }
            }
            ans=min(ans, max_flow(s*2,k*2+1));
        }
    }

    return ans==INF?n:ans;
}

int main()
{
    //freopen("input.txt", "r", stdin);
    int a, b;
    char c;
    while(cin>>n>>m)
    {
        edge_cnt=0;
        memset(edge,0,sizeof(edge));
        for(int i=n*2; i>=0; i--) vect[i].clear();

        for(int i=0; i<n; i++)  //拆点
        {
            add_node(i*2, i*2+1, 1, 0);
            add_node(i*2+1, i*2, 0, 0);
        }

        for(int i=0; i<m; i++)
        {
            while(c=getchar(), c!=‘(‘ );
            scanf("%d%c%d%c",&a,&c,&b,&c);

            add_node(a*2+1, b*2, INF, 0 );  //每条无向边拆2条有向
            add_node(b*2, a*2+1, 0, 0 );

            add_node(b*2+1, a*2, INF, 0);
            add_node(a*2, b*2+1, 0, 0);
        }
        printf("%d\n",cal());
    }
    return 0;
}

AC代码(穷举S和T)

时间: 2024-10-14 07:59:53

UVA 1660 Cable TV Network 电视网络(无向图,点连通度,最大流)的相关文章

UVA 1660 Cable TV Network

题意: 求一个无向图的点连通度. 分析: 把一个点拆成一个入点和一个出点,之间连一条容量为1的有向边,表示能被用一次.最大流求最小割即可.套模板就好 代码; #include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <queue>using namespace std;const int maxn=110;#define INF 1<

UVa 1660 Cable TV Network (最大流,最小割)

题意:求一个无向图的点连通度. 析:把每个点拆成两个,然后中间连接一个容量为1的边,然后固定一个源点,枚举每个汇点,最小割. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream>

ZOJ 2182 Cable TV Network(无向图点割-最大流)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2182 题意:给出一个无向图,问最少删掉多少个顶点之后图变得不连通? 思路:将原图每个点拆点(i,i+n),连边<i,i+n,1>,对原图的边(u,v),连边<u+n,v,INF>,<v+n,u,INF>.然后对于每对顶点(i,j)跑最大流(i+n,j).所有最大流的最小值即为答案. struct node { int v,cap,nex

POJ 1966 Cable TV Network(无向图的顶点连通度)

POJ 1966 Cable TV Network 链接:http://poj.org/problem?id=1966 题意:有线电视网络中,中继器的连接是双向的.如果网络中任何两个中继器之间至少有一条路,则中继器网络称为是连通的,否则中继器网络是不连通的.一个空的网络.以及只有一个中继器的网络被认为是连通的.具有n 个中继器的网络的安全系数f 被定义成: (1) f 为n,如果不管删除多少个中继器,剩下的网络仍然是连通的: (2) f 为删除最少的顶点数,使得剩下的网络不连通. 现在给定一个有

Cable TV Network 顶点连通度 (最大流算法)

Cable TV Network 题目抽象:给出含有n个点顶点的无向图,给出m条边.求定点联通度   K 算法:将每个顶点v拆成 v'   v''  ,v'-->v''的容量为1.           对于原图中的边(u,v)   连边   u''--->v'    v''-->u'.    求每对定点的P(u,v);以u为源点,v为汇点. 我们只需固定一个顶点,枚举其它汇点. 1 #include <iostream> 2 #include <cstdio> 3

POJ 1966 Cable TV Network(顶点连通度的求解)

Cable TV Network Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 4678   Accepted: 2163 Description The interconnection of the relays in a cable TV network is bi-directional. The network is connected if there is at least one interconnecti

POJ 1966 Cable TV Network

Cable TV Network Time Limit: 1000ms Memory Limit: 30000KB This problem will be judged on PKU. Original ID: 196664-bit integer IO format: %lld      Java class name: Main The interconnection of the relays in a cable TV network is bi-directional. The ne

POJ1966.Cable TV Network——无向图的点连通度

http://poj.org/problem?id=1966 题目描述: 有线电视网络中,中继器的连接是双向的.如果网络中任何两个中继器之间至少有一条路,则中继器网络称为是连通的,否则中继器网络是不连通的.一个空的网络.以及只有一个中继器的网络被认为是连通的.具有n 个中继器的网络的安全系数f 被定义成: (1) f 为n,如果不管删除多少个中继器,剩下的网络仍然是连通的: (2) f 为删除最少的顶点数,使得剩下的网络不连通. 分析: 本题中的安全系数f 实际上就是无向图的顶点连通度κ(G).

UVa1660 Cable TV Network (无向图,点连通度,最大流)

链接:http://bak3.vjudge.net/problem/UVA-1660 分析:这篇博客讲的很详细.http://www.cnblogs.com/xcw0754/p/4662429.html 1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 7 const int maxn = 100 +