排座位
时间限制
150 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越
布置宴席最微妙的事情,就是给前来参宴的各位宾客安排座位。无论如何,总不能把两个死对头排到同一张宴会桌旁!这个艰巨任务现在就交给你,对任何一对客人,请编写程序告诉主人他们是否能被安排同席。
输入格式:
输入第一行给出3个正整数:N(<= 100),即前来参宴的宾客总人数,则这些人从1到N编号;M为已知两两宾客之间的关系数;K为查询的条数。随后M行,每行给出一对宾客之间的关系,格式为:“宾客1 宾客2 关系”,其中“关系”为1表示是朋友,-1表示是死对头。注意两个人不可能既是朋友又是敌人。最后K行,每行给出一对需要查询的宾客编号。
这里假设朋友的朋友也是朋友。但敌人的敌人并不一定就是朋友,朋友的敌人也不一定是敌人。只有单纯直接的敌对关系才是绝对不能同席的。
输出格式:
对每个查询输出一行结果:如果两位宾客之间是朋友,且没有敌对关系,则输出“No problem”;如果他们之间并不是朋友,但也不敌对,则输出“OK”;如果他们之间有敌对,然而也有共同的朋友,则输出“OK but...”;如果他们之间只有敌对关系,则输出“No way”。
输入样例:7 8 4 5 6 1 2 7 -1 1 3 1 3 4 1 6 7 -1 1 2 1 1 4 1 2 3 -1 3 4 5 7 2 3 7 2输出样例:
No problem OK OK but... No way
并查集
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int f[105];
int map[105][105];
int find_set(int x)
{
if(x!=f[x])
return find_set(f[x]);
else
return x;
}
void Union(int x,int y)//合并
{
x=find_set(x);
y=find_set(y);
if(x!=y)
f[x]=y;
}
int main()
{
int n,m,k;
int i,j;
int x,y,z;
cin>>n>>m>>k;
for(i=1;i<=n;i++)
f[i]=i;
for(i=1;i<=m;i++)
{
cin>>x>>y>>z;
map[x][y]=map[y][x]=z;
if(z==1)
Union(x,y);
}
int judge1,judge2;
for(i=0;i<k;i++)
{
cin>>judge1>>judge2;
if(map[judge1][judge2]==1)//
cout<<"No problem"<<endl;
else if(map[judge1][judge2]==-1)
{
if(find_set(judge1)==find_set(judge2))
cout<<"OK but..."<<endl;
else
cout<<"No way"<<endl;
}
else
cout<<"OK"<<endl;
}
return 0;
}
例二:将所给的人按照每3个分一组,并且每组的三个人要是好朋友,如果可以满足这个条件输出Yes,否则输出No
写这道题的时候好多人刚开始都对人数进行了预判来剪枝,因为这个错了很多遍,我写的时候本来也想把剪枝写上,但写着写着忘了也没加,反倒直接对了。
按理说加剪枝更好,不懂这个梗啊。。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
int f[5005];
int find_set(int x)
{
if(x!=f[x])
return find_set(f[x]);
return x;
}
void unio(int x,int y)
{
int t;
x=find_set(x);
y=find_set(y);
f[x]=y;
}
int main()
{
int n,m;
int a[5005],b[5005],c[5005];
while(scanf("%d %d",&n,&m)!=EOF)
{
int i;
for(i=1;i<=n;i++)
f[i]=i;
for(i=0;i<m;i++)
{
scanf("%d %d",&a[i],&b[i]);
unio(a[i],b[i]);
}
for(i=1;i<=n;i++)
f[i]=find_set(f[i]);
sort(f+1,f+n+1);
memset(c,0,sizeof(c));
int j=0,flag=0;
c[0]=1;
for(i=2;i<=n;i++)
{
if(f[i]==f[i-1])
c[j]++;
else
c[++j]=1;
}
for(i=0;i<=j;i++)
{
if(c[i]%3!=0)
{
flag=1;
break;
}
}
if(flag==0)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
HDU 6152
Friend-Graph
题意:要求所给的人里既不能有任意三人完全不是朋友,也不能有任意三个人两两之间都是朋友
经过演算发现两两之间是朋友的个数是有限制的,我先用这个剪枝,时间就会快一点
#include<iostream>
#include<string>
#include<cstring>
#include<stdio.h>
#include <algorithm>
#include<math.h>
using namespace std;
int a[3500][1700];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
int cnt0=0,cnt1=0;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
for(int j=i+1;j<=n;j++)
{
scanf("%d",&a[i][j]);
if(a[i][j]==0)
cnt0++;
if(a[i][j]==1)
cnt1++;
}
}
int h=0;
if(n<3)
h=1;
else if(n==3)
{
if(cnt0==0||cnt0==3)
h=1;
}
else
{
int x=n*(n-1)/2;
if(cnt0>=n-1&&cnt0<=x-(n-1))
{
for(int i=1; i<n; i++)
{
for(int j=i+1; j<n; j++)
{
for(int k=j+1; k<=n; k++)
{
if(a[i][j]==a[i][k]&&a[i][k]==a[j][k])
{
h=1;
break;
}
}
if(h==1)
break;
}
if(h==1)
break;
}
}
else
h=1;
}
if(h==0)
printf("Great Team!\n");
else
printf("Bad Team!\n");
}
return 0;
}