UVA-818 Cutting Chains
这个题想了很久,还是没有思路,就去看了别的大佬的博客
结果大佬们好像都喜欢用二进制,我作为一个一看到二进制就头疼的渣渣
最后还是看了这位大佬的
没有二进制!!
https://blog.csdn.net/playwfun/article/details/44346619
先上一下易出错的测试数据
Sample Input
2 1 2 1 2 -1 -1
2 1 2 2 1 1 2 2 1 -1 -1
3 1 2 -1 -1
0
这里没有用二进制,而是用双递归来代替
dfs(p+1,d);
int temp[2][20];
for(int i=1; i<=n; i++)
{
temp[0][i]=te[p][i];
temp[1][i]=te[i][p];
te[p][i]=te[i][p]=0;
}
dfs(p+1,d+1);
for(int i=1; i<=n; i++)
{
te[p][i]=temp[0][i];
te[i][p]=temp[1][i];
}
//对于每个环都可以选择是否open
temp数组用来储存te的数据,dfs之后要将数据再改回去
dfs中的参数 p是当前考虑的环的编号,d是当前打开了d个环
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int te[20][20];
int n,ans;
int vis[30];
bool judge()//如果分支大于2,return false
{
int c[30]= {0};
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(te[i][j])
{
if(++c[i]>=5)
return false;
if(++c[j]>=5)
return false;
}
}
}
return true;
}
bool huan(int u,int fa)//如果是环return true
{
vis[u]=1;
for(int v=1; v<=n; v++)
{
if(v!=u&&v!=fa)
{
if(te[u][v]||te[v][u])
{
if(vis[v])
return true;
else
huan(v,u);
}
}
}
return false;
}
void dfs(int p,int d)
{
if(d>ans)
return;
if(p==n+1)
{
if(judge())
{
int ok=1;
memset(vis,0,sizeof(vis));
int cnt=0;
for(int i=1; i<=n; i++)
{
if(!vis[i])
{
cnt++;
if(huan(i,-1))
ok=0;
}
}
//cnt是链数
//比如1 2 2 3 4 5
//本来是有两条链,但是如果将4 open(te[4][5]=0,te[5][4]=0),4与5就不再相连
//链数就变成了3,此时d是1
//下面的cnt=cnt-d,结果中的cnt就是原来的链数
if(ok)
{
cnt=cnt-d;
if(cnt<=d+1)//本来的链数必须不大于d+1,不然无法将所有的环连成一条链
ans=d;
}
}
return;
}
dfs(p+1,d);
int temp[2][20];
for(int i=1; i<=n; i++)
{
temp[0][i]=te[p][i];
temp[1][i]=te[i][p];
te[p][i]=te[i][p]=0;
}
dfs(p+1,d+1);//如果将p环open,就要将p环连接的所有环都断开
for(int i=1; i<=n; i++)
{
te[p][i]=temp[0][i];
te[i][p]=temp[1][i];
}
}
int main()
{
int ccase=0;
while(cin>>n&&n)
{
ans=n;
ccase++;
int x,y;
memset(te,0,sizeof(te));
while(cin>>x>>y)
{
if(x==-1)
break;
te[x][y]=te[y][x]=1;
}
dfs(1,0);
printf("Set %d: Minimum links to open is %d\n",ccase,ans);
}
return 0;
}