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号点为源点也能过,当然穷举两点也能过。
#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 电视网络(无向图,点连通度,最大流)的更多相关文章
- UVA 1660 Cable TV Network
题意: 求一个无向图的点连通度. 分析: 把一个点拆成一个入点和一个出点,之间连一条容量为1的有向边,表示能被用一次.最大流求最小割即可.套模板就好 代码; #include <iostream ...
- UVa 1660 Cable TV Network (最大流,最小割)
题意:求一个无向图的点连通度. 析:把每个点拆成两个,然后中间连接一个容量为1的边,然后固定一个源点,枚举每个汇点,最小割. 代码如下: #pragma comment(linker, "/ ...
- Cable TV Network 顶点连通度 (最大流算法)
Cable TV Network 题目抽象:给出含有n个点顶点的无向图,给出m条边.求定点联通度 K 算法:将每个顶点v拆成 v' v'' ,v'-->v''的容量为1. ...
- UVA1660 Cable TV Network (无向图的点连通度)
题意:求一个无向图的点连通度. 把一个点拆成一个入点和一个出点,之间连一条容量为1的有向边,表示能被用一次.最大流求最小割即可. 一些细节的东西:1.源点固定,汇点要枚举一遍,因为最小割割断以后会形成 ...
- ZOJ 2182 Cable TV Network(无向图点割-最大流)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2182 题意:给出一个无向图,问最少删掉多少个顶点之后图变得不连通 ...
- UVA1660 电视网络 Cable TV Network
题目地址:UVA1660 电视网络 Cable TV Network 枚举两个不直接连通的点 \(S\) 和 \(T\) ,求在剩余的 \(n-2\) 个节点中最少去掉多少个可以使 \(S\) 和 \ ...
- POJ 1966 Cable TV Network(顶点连通度的求解)
Cable TV Network Time Limit: 1000MS Memory Limit: 30000K Total Submissi ...
- POJ 1966 Cable TV Network
Cable TV Network Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 4702 Accepted: 2173 ...
- POJ 1966 Cable TV NETWORK(网络流-最小点割集)
Cable TV NETWORK The interconnection of the relays in a cable TV net ...
随机推荐
- C# Socket连接超时设置
问题描述: 对于C# Socket没有超时设置的选项,默认情况下进行Socket连接,返回连接失败需要20-30s时间,严重影响用户体验 问题解决: Socket服务器端: Socke ...
- java文件操作(输出目录、查看磁盘符)
问题描述: java操作文件,所有硬盘中所有文件路径 问题解决: (1)查看所有磁盘文件 注: 如上所示,使用接口 File.listRoots()可以返回所有磁盘文件,通过f ...
- 你真的知道css三种存在样式(外联样式、内部样式、内联样式)的区别吗?
css样式在html中有三种存在形态: 内联样式:<div style="display: none"></div> 内部样式: <style> ...
- memmove和memcpy 以及strcmp strcpy几个库函数的实现
memmove和memcpy 1.memmove 函数原型:void *memmove(void *dest, const void *source, size_t count) 返回值说明:返回指向 ...
- 01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制
Nhibernate 并发控制 [1]悲观并发控制 正在使用数据的操作,加上锁,使用完后解锁释放资源. 使用场景:数据竞争激烈,锁的成本低于回滚事务的成本 缺点:阻塞,可能死锁 [2]乐观并发控制: ...
- Unity3D研究院之IOS本地消息通知LocalNotification的使用
原地址:http://www.xuanyusong.com/archives/2632 现在的游戏里一般都会有本地消息,比如每天定时12点或者下午6点告诉玩家进入游戏领取体力.这种东西没必要服务器 ...
- Unity3d修改FBX文件的动画名方法
问题描述:FBX文件导入Unity3d后的动画名字一般都是 “Take 001”并且无法修改!如何修改它呢? 解决方法:解决方法其实很简单,只要你按照Unity3d的FBX文件命名规则,压根就不会存在 ...
- java001-Helloworld
public class test05 { public static void main(String[] args) { System.out.println("Hello World! ...
- POJ 1745
#include <iostream> #define MAXN 10005 using namespace std; int _m[MAXN]; ]; int main() { //fr ...
- **PHP随机数算法
<?php $tmp = range(1,30);print_r(array_rand($tmp,10));?> 输出: Array( [0] => 6 [1] => 8 [2 ...