题目:BZOJ4160.
题目大意:给定一张
n
n
n个点
m
m
m条边无向图,要求给每条边定向,求定向后有向图上的最长路最短是多少.
1
≤
n
≤
15
,
1
≤
m
≤
100
1\leq n\leq 15,1\leq m\leq 100
1≤n≤15,1≤m≤100.
首先,最短的最长路并不好算,考虑利用Dilworth定理,将问题转化为求最小的最小反链划分.
然后设 d p [ S ] dp[S] dp[S]表示点集 S S S最少需要被划分为几个反链,若 S S S内的点都没有直接连通则 d p [ S ] = 1 dp[S]=1 dp[S]=1,否则枚举子集来转移.
时间复杂度 O ( 2 n n 2 + 3 n ) O(2^nn^2+3^n) O(2nn2+3n).
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define Abigail inline void
typedef long long LL;
const int N=15,M=100,C=26,INF=(1<<30)-1;
int id[C+9];
int n,m,e[N+9][N+9];
int dp[(1<<N)+9];
Abigail into(){
scanf("%d",&m);
for (int i=1;i<=m;++i){
char s[2][2];
scanf("%s%s",s[0],s[1]);
int x=s[0][0]-'A',y=s[1][0]-'A';
if (!id[x]) id[x]=++n;
if (!id[y]) id[y]=++n;
e[id[x]-1][id[y]-1]=1;
}
}
Abigail work(){
for (int g0=1;g0<1<<n;++g0){
dp[g0]=1;
for (int i=0;i<n;++i)
for (int j=0;j<n;++j)
if (g0>>i&1&&g0>>j&1&&e[i][j]) dp[g0]=INF;
for (int g1=(g0-1)&g0;g1;g1=(g1-1)&g0) dp[g0]=min(dp[g0],dp[g1]+dp[g0^g1]);
}
}
Abigail outo(){
printf("%d\n",dp[(1<<n)-1]-2);
}
int main(){
into();
work();
outo();
return 0;
}