1064: [Noi2008]假面舞会
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2240 Solved: 1083
[ Submit][ Status][ Discuss]
Description
一年一度的假面舞会又开始了,栋栋也兴致勃勃的参加了今年的舞会。今年的面具都是主办方特别定制的。每个参加舞会的人都可以在入场时选择一 个自己喜欢的面具。每个面具都有一个编号,主办方会把此编号告诉拿该面具的人。为了使舞会更有神秘感,主办方把面具分为k (k≥3)类,并使用特殊的技术将每个面具的编号标在了面具上,只有戴第i 类面具的人才能看到戴第i+1 类面具的人的编号,戴第k 类面具的人能看到戴第1 类面具的人的编号。 参加舞会的人并不知道有多少类面具,但是栋栋对此却特别好奇,他想自己算出有多少类面具,于是他开始在人群中收集信息。 栋栋收集的信息都是戴第几号面具的人看到了第几号面具的编号。如戴第2号面具的人看到了第5 号面具的编号。栋栋自己也会看到一些编号,他也会根据自己的面具编号把信息补充进去。由于并不是每个人都能记住自己所看到的全部编号,因此,栋栋收集的信 息不能保证其完整性。现在请你计算,按照栋栋目前得到的信息,至多和至少有多少类面具。由于主办方已经声明了k≥3,所以你必须将这条信息也考虑进去。
Input
第一行包含两个整数n, m,用一个空格分隔,n 表示主办方总共准备了多少个面具,m 表示栋栋收集了多少条信息。接下来m 行,每行为两个用空格分开的整数a, b,表示戴第a 号面具的人看到了第b 号面具的编号。相同的数对a, b 在输入文件中可能出现多次。
Output
包含两个数,第一个数为最大可能的面具类数,第二个数为最小可能的面具类数。如果无法将所有的面具分为至少3 类,使得这些信息都满足,则认为栋栋收集的信息有错误,输出两个-1。
Sample Input
Sample Output
这题题意可以转换成染色问题:
对于每个节点,它的所有后继颜色必须全部相同,并且不能和它相同
例如样1->2,1->3,那么2和3的颜色必须一样,且1和2,1和3的颜色必须不一样
按上面的条件给所有点染色,问最多可以用多少种颜色,最少要用多少种颜色(>=3)
如果最多可以用的颜色数量<3,输出-1 -1
结论:
先将图处理一下,所有的边权值设为1,然后把它转成无向图,反向边的权值设为-1
两种情况:
①如果无向图中存在环:
colmax = 所有环边权和的最大公约数,colmin = 所有环边权和的最小公约数(要求>=3)
②无向图中不存在环:
找到每个连通图的最长权值链,加在一起就是colmax,colmin = 3
#include<stdio.h>
#include<string.h>
#include<vector>
#include<queue>
#include<stdlib.h>
using namespace std;
vector<int> G[100005], GF[100005];
queue<int> q;
int bet, vis[100005], len[100005], in[100005], dp[100005], ans;
int Gcd(int x, int y)
{
if(x==0) return y;
if(y==0) return x;
return Gcd(y, x%y);
}
void Sech(int u, int val)
{
int i, v;
len[u] = val;
vis[u] = 1;
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(vis[v]==0)
Sech(v, val+1);
else
ans = Gcd(ans, abs(len[u]-len[v]+1));
}
for(i=0;i<GF[u].size();i++)
{
v = GF[u][i];
if(vis[v]==0)
Sech(v, val-1);
else
ans = Gcd(ans, abs(len[u]-len[v]-1));
}
}
void Sech2(int u)
{
int i, v;
vis[u] = 1;
bet = max(bet, dp[u]);
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
if(vis[v]==0)
Sech2(v);
}
for(i=0;i<GF[u].size();i++)
{
v = GF[u][i];
if(vis[v]==0)
Sech2(v);
}
}
int main(void)
{
int i, j, x, y, n, m;
//freopen("in.txt", "r", stdin);
scanf("%d%d", &n, &m);
for(i=1;i<=m;i++)
{
scanf("%d%d", &x, &y);
G[x].push_back(y);
GF[y].push_back(x);
in[y]++;
}
for(i=1;i<=n;i++)
{
if(vis[i]==0)
Sech(i, 0);
}
if(ans)
{
if(ans<3)
printf("-1 -1\n");
else
{
for(i=3;i<=ans;i++)
{
if(ans%i==0)
{
printf("%d %d\n", ans, i);
break;
}
}
}
}
else
{
memset(vis, 0, sizeof(vis));
for(i=1;i<=n;i++)
{
if(in[i]==0)
{
dp[i] = 1;
q.push(i);
vis[i] = 1;
}
}
while(q.empty()==0)
{
x = q.front();
q.pop();
vis[x] = 0;
for(j=0;j<G[x].size();j++)
{
y = G[x][j];
if(dp[x]+1>dp[y])
{
dp[y] = dp[x]+1;
if(vis[y]==0)
{
vis[y] = 1;
q.push(y);
}
}
}
for(j=0;j<GF[x].size();j++)
{
y = GF[x][j];
if(dp[x]-1>dp[y])
{
dp[y] = dp[x]-1;
if(vis[y]==0)
{
vis[y] = 1;
q.push(y);
}
}
}
}
for(i=1;i<=n;i++)
{
bet = 0;
if(vis[i]==0)
Sech2(i);
ans += bet;
}
if(ans>=3)
printf("%d 3\n", ans);
else
printf("-1 -1\n");
}
return 0;
}