[SPOJ 287] Smart Network Administrator 二分答案+网络流

解决一个村庄连接互联网的问题,通过使用最大流算法找到所需的最小缆线颜色数量。

The citizens of a small village are tired of being the only inhabitants around without a connection to the Internet. After nominating the future network administrator, his house was connected to the global network. All users that want to have access to the Internet must be connected directly to the admin's house by a single cable (every cable may run underground along streets only, from the admin's house to the user's house). Since the newly appointed administrator wants to have everything under control, he demands that cables of different colors should be used. Moreover, to make troubleshooting easier, he requires that no two cables of the same color go along one stretch of street.

Your goal is to find the minimum number of cable colors that must be used in order to connect every willing person to the Internet.

Input

t [the number of test cases, t<=500]
n m k [n <=500 the number of houses (the index of the admin's house is 1)]
[m the number of streets, k the number of houses to connect]
hh2 ... hk [a list of k houses wanting to be conected to the network, 2<=hi<=n]
[The next m lines contain pairs of house numbers describing street ends]
e11 e12
e21 e22
...
emem2
[next cases]

Output

For each test case print the minimal number of cable colors necessary to make all the required connections.

Example

Input:
2
5 5 4
2 3 4 5
1 2
1 3
2 3
2 4
3 5
8 8 3
4 5 7
1 2
1 8
8 7
1 3
3 6
3 2
2 4
2 5

Output:
2
1

Warning: large Input/Output data, be careful with certain languages

 

【题目大意】

一座村庄有N户人家。只有第一家可以连上互联网,其他人家要想上网必须拉一根缆线通过若干条街道连到第一家。每一根完整的缆线只能有一种颜色。网管有一个要求,各条街道内不同人家的缆线必须不同色,且总的不同颜色小。

求在指定的K户人家都能上网的前提下,最小的不同颜色种数。(1 <= N <= 500)

二分颜色种数X,每一条边的容量设为X 并且s->所有重要的用户,容量为1 跑一遍最大流 flow>=k 满足

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<cstring>
  6 using namespace std;
  7 const int N=505,INF=1999999999;
  8 int gi(){
  9     int str=0;char ch=getchar();
 10     while(ch>'9' || ch<'0')ch=getchar();
 11     while(ch>='0' && ch<='9')str=str*10+ch-'0',ch=getchar();
 12     return str;
 13 }
 14 int head[N],num=1,n,m,k,sta;
 15 int s=0,T=1;
 16 struct Lin{
 17     int next,to,dis;
 18 }a[N*N];
 19 struct Edge{
 20     int x,y;
 21 }e[N*N];
 22 int imp[N];
 23 void init(int x,int y,int dis){
 24     a[++num].next=head[x];
 25     a[num].to=y;
 26     a[num].dis=dis;
 27     head[x]=num;
 28     a[++num].next=head[y];
 29     a[num].to=x;
 30     a[num].dis=0;
 31     head[y]=num;
 32 }
 33 int q[N*10],dep[N];
 34 bool bfs()
 35 {
 36     memset(dep,0,sizeof(dep));
 37     int x,u,t=0,sum=1;
 38     q[1]=s;dep[s]=1;
 39     while(t!=sum)
 40     {
 41         x=q[++t];
 42         for(int i=head[x];i;i=a[i].next){
 43             u=a[i].to;
 44             if(dep[u] || a[i].dis<=0)continue;
 45             dep[u]=dep[x]+1;q[++sum]=u;
 46         }
 47     }
 48     return dep[T];
 49 }
 50 int dfs(int x,int flow){
 51     if(x==T || !flow)return flow;
 52     int u,sum=0,tmp;
 53     for(int i=head[x];i;i=a[i].next){
 54         u=a[i].to;
 55         if(dep[u]!=dep[x]+1 || a[i].dis<=0)continue;
 56         tmp=dfs(u,min(flow,a[i].dis));
 57         a[i].dis-=tmp;a[i^1].dis+=tmp;
 58         sum+=tmp;flow-=tmp;
 59         if(!flow)break;
 60     }
 61     return sum;
 62 }
 63 int maxflow()
 64 {
 65     int qq,tot=0;
 66     while(bfs()){
 67         qq=dfs(s,INF);
 68         while(qq)tot+=qq,qq=dfs(s,INF);
 69     }
 70     return tot;
 71 }
 72 void Clear(){
 73     memset(head,0,sizeof(head));
 74     num=1;
 75 }
 76 bool check(int ff)
 77 {
 78     Clear();
 79     for(int i=1;i<=k;i++){
 80         init(s,imp[i],1);
 81     }
 82     for(int i=1;i<=m;i++){
 83         init(e[i].x,e[i].y,ff);init(e[i].y,e[i].x,ff);
 84     }
 85     int tp=maxflow();
 86     return tp>=k;
 87 }
 88 void work()
 89 {
 90     int x,y;
 91     n=gi();m=gi();k=gi();
 92     for(int i=1;i<=k;i++)imp[i]=gi();
 93     for(int i=1;i<=m;i++){
 94         e[i].x=gi();e[i].y=gi();
 95     }
 96     int l=0,r=k,mid,ans;
 97     while(l<=r){
 98         mid=(l+r)>>1;
 99         if(check(mid))ans=mid,r=mid-1;
100         else l=mid+1;
101     }
102     printf("%d\n",ans);
103 }
104 int main()
105 {
106     //freopen("pp.in","r",stdin);
107     int T=gi();
108     while(T--){
109         work();
110     }
111     return 0;
112 }

 

转载于:https://www.cnblogs.com/Yuzao/p/6853585.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值