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
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 }