bzoj4160: [Neerc2009]Exclusive Access 2

Description

给出 N 个点M 条边的无向图,定向得到有向无环图,使得最长路最短。
N ≤ 15, M ≤ 100

 

Input

第一行一个数M (1≤M≤100).
接下来M行,每行两个大写字母(L 到 Z),最多出线15个不同的大写字母。每行的两个大写字母不会相同

 

Output

第一行输出最长路最短的数值-1。
 

 

Sample Input

3
P Q
Q R
R P

Sample Output

1
 
 
 
 
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define inf 1061109567
 7 using namespace std;
 8 char a[2],b[2];
 9 int n,m,u,v,cnt,pos[16],g[16][16],can[1<<16],f[1<<16],list[16];
10 int calc(int cnt){
11     if (f[cnt]<inf) return f[cnt];
12     int ans=inf,ncnt=cnt;
13     while (ncnt){
14         if (can[ncnt]) ans=min(ans,calc(cnt^ncnt)+1);
15         ncnt=(ncnt-1)&cnt;
16     }
17     return f[cnt]=ans;
18 }
19 int main(){
20     scanf("%d",&m);
21     memset(pos,-1,sizeof(pos));
22     for (int i=1;i<=m;i++){
23         scanf("%s%s",a,b),u=a[0]-'L',v=b[0]-'L';
24         if (pos[u]==-1) pos[u]=n++;
25         if (pos[v]==-1) pos[v]=n++;
26         g[pos[u]][pos[v]]=g[pos[v]][pos[u]]=1;
27     }
28     for (int i=0;i<(1<<n);i++){
29         cnt=0,can[i]=1;
30         for (int j=0;j<n;j++) if (i&(1<<j)) list[++cnt]=j;
31         for (int a=1,u=list[a];a<=cnt&&can[i];u=list[++a])
32             for (int b=1,v=list[b];b<=cnt&&can[i];v=list[++b])
33                 if (g[u][v]) can[i]=0;
34     }
35     memset(f,63,sizeof(f));
36     f[0]=0;
37     printf("%d\n",calc((1<<n)-1)-2);
38     return 0;
39 }

 

posted @ 2015-09-22 14:15  chenyushuo  阅读(335)  评论(0编辑  收藏  举报