POJ 1129 Channel Allocation
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 14191 | Accepted: 7229 |
Description
Since the radio frequency spectrum is a precious resource, the number of channels required by a given network of repeaters should be minimised. You have to write a program that reads in a description of a repeater network and determines the minimum number of channels required.
Input
Following the number of repeaters is a list of adjacency relationships. Each line has the form:
A:BCDH
which indicates that the repeaters B, C, D and H are adjacent to the repeater A. The first line describes those adjacent to repeater A, the second those adjacent to B, and so on for all of the repeaters. If a repeater is not adjacent to any other, its line has the form
A:
The repeaters are listed in alphabetical order.
Note that the adjacency is a symmetric relationship; if A is adjacent to B, then B is necessarily adjacent to A. Also, since the repeaters lie in a plane, the graph formed by connecting adjacent repeaters does not have any line segments that cross.
Output
Sample Input
2
A:
B:
4
A:BC
B:ACD
C:ABD
D:BC
4
A:BCD
B:ACD
C:ABD
D:ABC
0
Sample Output
1 channel needed.
3 channels needed.
4 channels needed.
/*-------------超时代码---------------*/
/*
一开始我直接用的dfs没有剪枝,就是dfs每一个点,枚举每一个频道,找到不相邻,就向下dfs,再加上回溯,每次复杂度是n^3,再加上题目询问的数据量有点大,就超时了。*/
/*--------------------------*/
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#define N 30
struct Edge{
int v,last;
}edge[N*N];
int head[N];
int sum=(<<)-,n,t=;
int flag[N],pd[N];
bool bb=false;
inline void add_edge(int u,int v)
{
++t;
edge[t].v=v;
edge[t].last=head[u];
head[u]=t;
}
inline void input()
{
char s[N];
for(int i=;i<=n;++i)
{
scanf("%s",s+);
int len=strlen(s+);
for(int j=;j<=len;++j)
add_edge(s[]-'A'+,s[j]-'A'+);
}
}
inline void dfs(int k)
{
if(k==n+)
{
int ans=;
for(int j=;j<=n;++j)
if(flag[j]) ans++;
sum=min(ans,sum);
return;
}
for(int i=;i<=n;++i)
{
int biaozhi=true;
for(int l=head[k];l;l=edge[l].last)
{
if(pd[edge[l].v]==i)
{
biaozhi=false;
break;
}
}
if(!biaozhi) continue;
pd[k]=i;
flag[i]++;
dfs(k+);
flag[i]--;
pd[k]=;
} }
int main()
{
while(scanf("%d",&n)==)
{
if(n==) break;
input();
dfs();
printf("%d channels needed.\n",sum);
memset(edge,,sizeof(edge));
memset(head,,sizeof(head));
sum=(<<)-;t=;bb=false;
memset(flag,,sizeof(flag));
}
return ;
}
/*-------------对于上面那个代码-----------------*/
特殊数据: A:B
B:
C:
D:
E:
F:
G:
H:
I:
用上面的代码来处理这个非常稀疏的图时间是很长的,因为for(i-->n)枚举频道中的if语句几乎始终成立,那么dfs的复杂度就到了n^n的增长速度,当n==8时,已经1.*^8多了,自然会超时,所以必须改为迭代加深搜索。限定搜索的深度,实际上是不会到n的
/*改成迭代加深搜索之后,速度果然快了许多。
还有一个值得注意的地方:当sum是1的时候,channel是单数形式,其他时候是复数形式(英语不好被坑了)
*/
#include<iostream>
using namespace std;
#include<cstdio>
#include<cstring>
#define N 30
struct Edge{
int v,last;
}edge[N*N];
int head[N];
bool vis[N][N]={false};
int sum=(<<)-,n,t=;
int pd[N];
bool flag=false;
inline void add_edge(int u,int v)
{
if(vis[u][v]||vis[v][u]) return ;
vis[u][v]=true;vis[v][u]=true;
++t;
edge[t].v=v;
edge[t].last=head[u];
head[u]=t;
++t;
edge[t].v=u;
edge[t].last=head[v];
head[v]=t;
}
inline void input()
{
char s[N];
for(int i=;i<=n;++i)
{
scanf("%s",s+);
int len=strlen(s+);
for(int j=;j<=len;++j)
add_edge(s[]-'A'+,s[j]-'A'+);
}
}
inline void dfs(int k,int minn)
{
if(k==n+)
{
flag=true;
return;
}
for(int i=;i<=minn;++i)
{
bool biaozhi=true;
for(int l=head[k];l;l=edge[l].last)
{
if(pd[edge[l].v]==i)
{
biaozhi=false;
break;
}
}
if(!biaozhi) continue;
pd[k]=i;
dfs(k+,minn);
if(flag) return;
pd[k]=;
} }
int main()
{
while(scanf("%d",&n)==)
{
if(n==) break;
input();
for(int i=;i<=n;++i)
{
dfs(,i);
if(flag)
{
sum=i;
memset(pd,,sizeof(pd));
break;
}else memset(pd,,sizeof(pd));
}
if(sum>)
printf("%d channels needed.\n",sum);
else printf("%d channel needed.\n",sum);
memset(edge,,sizeof(edge));
memset(head,,sizeof(head));
sum=(<<)-;t=;
memset(vis,false,sizeof(vis));
flag=false;
}
return ;
}