正反两张图
三棵树
求交集
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<ctime>
#include<cstdlib>
#include<climits>
#include<queue>
#include<vector>
#define LL long long
#define MOD 1000000007
using namespace std;
int cnt[4][2],num[4][1000005][2],nxt[4][1000005][2],head[4][50005][2],low,high,n,k,m,x,y,z,poi[50005];
bool low_mark[4][50005],high_mark[4][50005],vis[50005];
void add(int p1,int p2,int t,int p)
{
cnt[t][p]++;
num[t][cnt[t][p]][p]=p2;
nxt[t][cnt[t][p]][p]=head[t][p1][p];
head[t][p1][p]=cnt[t][p];
}
void bfs()
{
int i,p,h,t;
for(p=1;p<=k;p++)
{
memset(vis,0,sizeof(vis));
h=1;t=1;
poi[h]=1;
vis[1]=1;
while(h<=t)
{
for(i=head[p][poi[h]][0];i;i=nxt[p][i][0])
if(!vis[num[p][i][0]])
{
t++;
low_mark[p][num[p][i][0]]=1;
vis[num[p][i][0]]=1;
poi[t]=num[p][i][0];
}
h++;
}
}
low=n;
for(i=2;i<=n;i++)
{
low--;
for(p=1;p<=k;p++)
if(!low_mark[p][i])
{
low++;
break;
}
}
for(p=1;p<=k;p++)
{
memset(vis,0,sizeof(vis));
h=1;t=1;
poi[h]=1;
vis[1]=1;
while(h<=t)
{
for(i=head[p][poi[h]][1];i;i=nxt[p][i][1])
if(!vis[num[p][i][1]])
{
t++;
high_mark[p][num[p][i][1]]=1;
vis[num[p][i][1]]=1;
poi[t]=num[p][i][1];
}
h++;
}
}
high=1;
for(i=2;i<=n;i++)
{
high++;
for(p=1;p<=k;p++)
if(!high_mark[p][i])
{
high--;
break;
}
}
}
int main()
{
int i;
scanf("%d%d%d",&n,&k,&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z,0);
add(y,x,z,1);
}
bfs();
printf("%d %d",low,high);
return 0;
}