Marco Popo the Traveler
Time Limit: 2 Seconds Memory Limit: 65536 KB
Marco Popo, the famous traveler, is traveling around the country of ACM. There are colored high-ways between cities (of course there is at most one high-way between any two cities), and his goal is to drive along each high-way once and only once. There is a strange rule to be followed when driving along: the color of one's tyres must match that of the high-way. As a result, he has to change tyres all the way he travels.
Given the total number of cities and the high-way map, you should decide at least how many times Popo needs to change tyres. Notice that Popo only changes tyres in cities, and he is allowed to start and end with tyres of arbitrary color.
Input
There are several test cases. Each test case begins with a line containing the total number of cities N (0 < N <= 10), the total number of colors C (0 < C <= 6), and the total number of high-ways in the country H (0 < H <= 20). Then H lines follow, each has three integers a, b, and c (0 <= a, b < N, 0 <= c < C) separated with whitespaces. This denotes that there is a high-way between city a and city b with color c.
There is a single blank line between test cases. A test case with 0 terminates the input, and this test case is not to be processed.
Output
For each test case, print a line with the minimum number of times Popo has to change tyres, so that he can achieve his goal. Otherwise print a line containing "No" only.
Sample Input
4 3 5
0 1 0
1 2 1
2 3 0
3 0 1
0 2 2
4 3 6
0 1 0
1 2 1
2 3 0
3 0 1
0 2 2
1 3 2
0 0 0
Sample Output
4
No
Author: SHI, Xiaohan
Source: Zhejiang University Local Contest 2004
#include<iostream>
#include<algorithm>
#include<string>
#include<map>//int dx[4]={0,0,-1,1};int dy[4]={-1,1,0,0};
#include<set>//int gcd(int a,int b){return b?gcd(b,a%b):a;}
#include<vector>
#include<cmath>
#include<stack>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
#define ll long long
#define MAX 1000000000
#define ms memset
#define maxn 100
using namespace std;
const int mod=1e9+7;
int n,c,m;
int x,y,z;///路和颜色
int d[20],cnt;///每个顶点的度数来判断是否有欧拉回路
/*
题目大意:给定n个顶点m条边的图,
每条边都有颜色,要求每次如果经历过不同颜色的路要换轮胎,
求最小的换轮胎次数。
首先什么情况下不可能?
图不是联通的情况下不可能,
或者是联通的但不是欧拉图。
下面的问题是如何存储边并以边为搜索对象?
把边用结构体存储起来,然后每一层都遍历结构体数组一遍。
*/
struct node
{
int tx,ty;
int cr;
node(){}
};
node seq[maxn];
int vis[maxn];///标记边的数组
int pre[maxn];
int Find(int x)
{
if(x == pre[x]) return x;
return pre[x] = Find(pre[x]);
}
void Union(int x,int y)
{
int fx=Find(x),fy=Find(y);
if(fx==fy) return ;
pre[fx]=fy;
}
void dfs(int pre,int lev,int t,int ans,int prec)///t为出发节点,lev为层数,pre为上一个的节点,ans存储的是目前换的轮胎次数,prec为上一个的颜色
{
/// cout<<pre<<" "<<t<<endl;
if(lev==m)
{
cnt=min(ans,cnt);
return ;
}
for(int i=0;i<m;i++)
{
if(vis[i]) continue;
if(seq[i].tx==t && seq[i].ty!=pre)
{
vis[i]=1;
if(prec!=seq[i].cr) dfs(t,lev+1,seq[i].ty,ans+1,seq[i].cr);
else dfs(t,lev+1,seq[i].ty,ans,seq[i].cr);
vis[i]=0;
}
else if(seq[i].ty==t && seq[i].tx != pre)
{
vis[i]=1;
if(prec!=seq[i].cr) dfs(t,lev+1,seq[i].tx,ans+1,seq[i].cr);
else dfs(t,lev+1,seq[i].tx,ans,seq[i].cr);
vis[i]=0;
}
}
}
int main()
{
while( scanf("%d%d%d",&n,&c,&m)
&& ( n || c || m ) )
{
memset(d,0,sizeof(d));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&x,&y,&z);
x++,y++,z++; ///下标平移
seq[i].tx=x , seq[i].ty=y , seq[i].cr=z;
d[x]++,d[y]++;
Union(x,y);
}
cnt=0;
for( int i=1 ; i<=n ; i++)
if(d[i]&1) cnt++;
if( cnt!=2 && cnt!=0 ) { puts("No"); continue; }///判断是否存在欧拉回路
cnt=0;
for(int i=1;i<=n;i++)
if(pre[i]==i) cnt++;
if(cnt>1) { puts("No"); continue; }///判断图是否连通
cnt=100000;///无穷大
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
dfs(-1,0,i,0,-1);
}
printf("%d\n",cnt-1);
}
return 0;
}