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

思路:

  如果只有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号点为源点也能过,当然穷举两点也能过。

  

 #include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=;
int n, m, edge_cnt;
vector<int> vect[N*];
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[], cpy[]; 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(,s);
flow[s]=INF; while(!que.empty())
{
int x=que.front();
que.pop_front();
for(int i=; 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=;
while(true)
{
memset(path,,sizeof(path));
memset(flow,,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^].flow-=tmp;
ed=cpy[t].from;
}
}
} int cal()
{
int ans=INF; for(int i=; i<edge_cnt; i++)
{
if( edge[i].from== && edge[i].to== && edge[i].cap> )
{
edge[i].cap=INF;
break;
}
}
for(int k=; k<n; k++) //枚举汇点
{
memcpy(cpy, edge, sizeof(edge));
for(int i=; i<edge_cnt; i++) //所有边
{
if( cpy[i].from==k* && cpy[i].to==k*+ &&cpy[i].cap> )
{
cpy[i].cap=INF;
break;
}
}
ans=min(ans, max_flow(,k*+));
}
return ans==INF?n:ans;
} int main()
{
freopen("input.txt", "r", stdin);
int a, b;
char c;
while(cin>>n>>m)
{
edge_cnt=;
memset(edge,,sizeof(edge));
for(int i=n*; i>=; i--) vect[i].clear(); for(int i=; i<n; i++) //拆点
{
add_node(i*, i*+, , );
add_node(i*+, i*, , );
} for(int i=; i<m; i++)
{
while(c=getchar(), c!='(' );
scanf("%d%c%d%c",&a,&c,&b,&c); add_node(a*+, b*, INF, ); //每条无向边拆2条有向
add_node(b*, a*+, , ); add_node(b*+, a*, INF, );
add_node(a*, b*+, , );
}
printf("%d\n",cal());
}
return ;
}

AC代码(任意源)

#include <bits/stdc++.h>
#define LL long long
#define pii pair<int,int>
#define INF 0x7f7f7f7f
using namespace std;
const int N=;
int n, m, edge_cnt;
vector<int> vect[N*];
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[], cpy[], old[]; 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(,s);
flow[s]=INF; while(!que.empty())
{
int x=que.front();
que.pop_front();
for(int i=; 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=;
while(true)
{
memset(path,,sizeof(path));
memset(flow,,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^].flow-=tmp;
ed=cpy[t].from;
}
}
} int cal()
{
int ans=INF;
for(int s=; s<n; s++) //枚举源点
{
memcpy(old, edge, sizeof(edge));
for(int i=; i<edge_cnt; i++)
{
if( old[i].from==s* && old[i].to==s*+ && old[i].cap> )
{
old[i].cap=INF;
break;
}
} for(int k=s+; k<n; k++) //枚举汇点
{
memcpy(cpy, old, sizeof(old));
for(int i=; i<edge_cnt; i++) //所有边
{
if( cpy[i].from==k* && cpy[i].to==k*+ &&cpy[i].cap> )
{
cpy[i].cap=INF;
break;
}
}
ans=min(ans, max_flow(s*,k*+));
}
} return ans==INF?n:ans;
} int main()
{
//freopen("input.txt", "r", stdin);
int a, b;
char c;
while(cin>>n>>m)
{
edge_cnt=;
memset(edge,,sizeof(edge));
for(int i=n*; i>=; i--) vect[i].clear(); for(int i=; i<n; i++) //拆点
{
add_node(i*, i*+, , );
add_node(i*+, i*, , );
} for(int i=; i<m; i++)
{
while(c=getchar(), c!='(' );
scanf("%d%c%d%c",&a,&c,&b,&c); add_node(a*+, b*, INF, ); //每条无向边拆2条有向
add_node(b*, a*+, , ); add_node(b*+, a*, INF, );
add_node(a*, b*+, , );
}
printf("%d\n",cal());
}
return ;
}

AC代码(穷举S和T)

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

  1. UVA 1660 Cable TV Network

    题意: 求一个无向图的点连通度. 分析: 把一个点拆成一个入点和一个出点,之间连一条容量为1的有向边,表示能被用一次.最大流求最小割即可.套模板就好 代码; #include <iostream ...

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

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

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

    Cable TV Network 题目抽象:给出含有n个点顶点的无向图,给出m条边.求定点联通度   K 算法:将每个顶点v拆成 v'   v''  ,v'-->v''的容量为1.       ...

  4. UVA1660 Cable TV Network (无向图的点连通度)

    题意:求一个无向图的点连通度. 把一个点拆成一个入点和一个出点,之间连一条容量为1的有向边,表示能被用一次.最大流求最小割即可. 一些细节的东西:1.源点固定,汇点要枚举一遍,因为最小割割断以后会形成 ...

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

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2182 题意:给出一个无向图,问最少删掉多少个顶点之后图变得不连通 ...

  6. UVA1660 电视网络 Cable TV Network

    题目地址:UVA1660 电视网络 Cable TV Network 枚举两个不直接连通的点 \(S\) 和 \(T\) ,求在剩余的 \(n-2\) 个节点中最少去掉多少个可以使 \(S\) 和 \ ...

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

                               Cable TV Network Time Limit: 1000MS   Memory Limit: 30000K Total Submissi ...

  8. POJ 1966 Cable TV Network

    Cable TV Network Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 4702   Accepted: 2173 ...

  9. POJ 1966 Cable TV NETWORK(网络流-最小点割集)

                                    Cable TV NETWORK The interconnection of the relays in a cable TV net ...

随机推荐

  1. C# Socket连接超时设置

    问题描述:         对于C# Socket没有超时设置的选项,默认情况下进行Socket连接,返回连接失败需要20-30s时间,严重影响用户体验 问题解决: Socket服务器端: Socke ...

  2. java文件操作(输出目录、查看磁盘符)

    问题描述:     java操作文件,所有硬盘中所有文件路径 问题解决:     (1)查看所有磁盘文件 注:     如上所示,使用接口 File.listRoots()可以返回所有磁盘文件,通过f ...

  3. 你真的知道css三种存在样式(外联样式、内部样式、内联样式)的区别吗?

    css样式在html中有三种存在形态: 内联样式:<div style="display: none"></div> 内部样式: <style> ...

  4. memmove和memcpy 以及strcmp strcpy几个库函数的实现

    memmove和memcpy 1.memmove 函数原型:void *memmove(void *dest, const void *source, size_t count) 返回值说明:返回指向 ...

  5. 01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制

    Nhibernate 并发控制 [1]悲观并发控制 正在使用数据的操作,加上锁,使用完后解锁释放资源. 使用场景:数据竞争激烈,锁的成本低于回滚事务的成本 缺点:阻塞,可能死锁 [2]乐观并发控制: ...

  6. Unity3D研究院之IOS本地消息通知LocalNotification的使用

    原地址:http://www.xuanyusong.com/archives/2632   现在的游戏里一般都会有本地消息,比如每天定时12点或者下午6点告诉玩家进入游戏领取体力.这种东西没必要服务器 ...

  7. Unity3d修改FBX文件的动画名方法

    问题描述:FBX文件导入Unity3d后的动画名字一般都是 “Take 001”并且无法修改!如何修改它呢? 解决方法:解决方法其实很简单,只要你按照Unity3d的FBX文件命名规则,压根就不会存在 ...

  8. java001-Helloworld

    public class test05 { public static void main(String[] args) { System.out.println("Hello World! ...

  9. POJ 1745

    #include <iostream> #define MAXN 10005 using namespace std; int _m[MAXN]; ]; int main() { //fr ...

  10. **PHP随机数算法

    <?php $tmp = range(1,30);print_r(array_rand($tmp,10));?> 输出: Array( [0] => 6 [1] => 8 [2 ...