带宽
Sample Input
A:FB;B:GC;D:GC;F:AGH;E:HD
#
Sample Output
A B C F G D H E -> 3
#include<cstdio>
#include<iostream>
#include<vector>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int INF = 10000;
int cnt,minb;
int temp[8],ans[8],pos[26];
vector<int> edge[26];//可以使用二维动态数组作为邻接表
void dfs(int cur,int c,int band){//当前答案中的位置,当前字符,当前带宽。
int i,j,t;
temp[cur] = c;
pos[c] = cur;
for(i = 0;i < edge[c].size(); ++i){
t = edge[c][i];
if(pos[t] != -1 && cur - pos[t] > band)
band = cur - pos[t];
}
if(band > minb){//紫书剪枝方式一,方式二这种方法不会实现。。。
pos[c] = -1;
return;
}
for(i = 0;i < 26; ++i){
if(pos[i] == -1 && edge[i].size())
dfs(cur + 1, i, band);
}
pos[c] = -1;
if(cur == cnt - 1){
if(band < minb){
for(i = 0;i < cnt; ++i)
ans[i] = temp[i];
minb = band;
}
pos[c] = -1;
}
}
int main(){
string s;
while((cin >> s) && (s[0] != '#')){
int i = 0;
for(int j = 0;j < 26; ++j)
edge[j].clear();
while(i < s.length()){
int fir = s[i] - 'A';
i += 2;
while(s[i] != ';' && i < s.length()){
int sec = s[i] - 'A';
edge[fir].push_back(sec);
edge[sec].push_back(fir);
++i;
}
++i;
}
memset(pos,-1,sizeof(pos));
cnt = 0;
minb = INF;
for(i = 0;i < 26; ++i){
if(edge[i].size()){
++cnt;
sort(edge[i].begin(),edge[i].end());
}
}
for(i = 0;i < 26; ++i){
if(edge[i].size()){
dfs(0,i,0);
}
}
for(i = 0;i < cnt; ++i){
printf("%c ",ans[i] + 'A');
}
printf("-> %d\n",minb);
}
return 0;
}