博主本来只想虐虐NOIP级别的暴力的.........
1. 本题状态很简单 , 哪些边用了 , 现在各点在哪里 , 把vector状态压缩成一个long long(代码中的ull 是 long long).
2. 转移的思路不复杂 , 看看哪些点能够从某一房间转移到另外一些房间 (不知道不预处理的版本能不能过 , 但是博主进行了一次预处理)
写写吧 , 虽然肯定超时 , 但是正解离你将要写的代码修改的不过3,4行 , 写完后尝试以下数据
就这样写 , 样例跑的很快 , 但是有一组数据肯定过不了
10 10
1 2 0
2 3 0
3 4 0
4 5 0
5 6 0
6 7 0
7 8 0
8 9 0
9 10 0
10 1 0
(博主想了各种优化方法 , 但是这个复杂度需要的优化不是常数级别的 , 也就是题目中的hint 所说的)
观察发现 , 其实状态是很有限的 , 因为很多路都只能经过一次 , 有用的状态尤其有限 (比如上述数据中从1到10然后回到1肯定是无用状态)
那该怎么处理呢? 请思考些时间 , 提示: 无用的状态是什么造成的
如果有思路了就动手吧 , 下面是代码 , 余下的所有分析在代码后
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <deque>
#include <stack>
#include <algorithm>
#include <set>
#include <queue>
#include <list>
using namespace std;
typedef long long ull;
const int maxn = 12;
const int maxm = 12;
int n , m;
int u[maxm] , v[maxm] , w[maxm];
vector<int> g[maxn];
int allow[maxm][1<<maxn];
ull q[10000000];
set<ull> dic;
ull encode(vector<int>& s)
{
ull res = 0;
for(int i=1;i<s.size();i++) res = res*11+s[i];
res = res*1200+s[0];
return res;
}
void decode(vector<int>& s , ull v)
{
s[0] = v%1200; v/=1200;
for(int i=(int)s.size()-1;i>=1;i--) s[i] = v%11 , v/=11;
}
int reachable[maxn][maxn];
int main(int argc, char *argv[]) {
while(cin>>n>>m)
{
dic.clear();
memset(allow, 0, sizeof(allow));
for(int i=1;i<=n;i++) g[i].clear();
memset(reachable, 0, sizeof(reachable));
for(int i=1;i<=m;i++) { cin>>u[i]>>v[i]>>w[i]; if(w[i]) g[u[i]].push_back(i); else reachable[u[i]][v[i]] = 1; }
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) reachable[i][j] |= ( reachable[i][k] && reachable[k][j] );
for(int i=1;i<(1<<9);i++) if(__builtin_popcount(i)>=3 && __builtin_popcount(i)<=5)
{
int num = 0;
for(int j=1;j<=9;j++) if(i&(1<<(j-1))) num+= j;
while(num>=10) num = num/10+num%10;
for(int j=1;j<=m;j++) if(w[j]==num) allow[j][i] = 1;
}
for(int j=1;j<=m;j++) if(w[j]==0) for(int i=1;i<512;i++) allow[j][i] = 1;
int book[maxn];
vector<int> beg;
set<int> ans; int Max = 0;
beg.push_back((1<<m)-1);
for(int i=1;i<=9;i++) beg.push_back(1);
int l = 0 , r = 0;
q[r++] = encode(beg);
dic.insert(encode(beg));
while(l!=r)
{
vector<int> now = beg , ne;
decode(now, q[l++]);
memset(book, 0, sizeof(book));
for(int i=1;i<now.size();i++) book[now[i]] |= (1<<(i-1));
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(reachable[i][j]) book[j] |= book[i];
if(book[n] && __builtin_popcount(book[n])>Max) { Max = __builtin_popcount(book[n]); ans.clear(); ans.insert(book[n]); }
else if(book[n] && __builtin_popcount(book[n])==Max) if(ans.count(book[n])==0) ans.insert(book[n]);
for(int i=1;i<=n;i++) for(int j=0;j<g[i].size();j++)
{
int way = g[i][j] , to = v[way];
if(!(now[0]&(1<<(way-1)))) continue;
for(int s = book[i];s>0;s = (s-1)&book[i]) if(allow[way][s])
{
ne = now;
for(int l=1;l<=9;l++) if(s& (1<<(l-1))) ne[l] = to;
if(w[way]) ne[0]^= 1<<(way-1);
ull hashNow = encode(ne);
if(dic.count(hashNow)) continue;
dic.insert(hashNow);
q[r++] = encode(ne);
}
}
}
vector<string> output;
for(set<int>::iterator i=ans.begin();i!=ans.end();++i)
{
int now = *i; string ins;
for(int j=1;j<=9;j++) if(now&(1<<(j-1))) ins = ins+((char)(j+'0'));
output.push_back(ins);
}
sort(output.begin(), output.end());
cout<<Max;
for(int i=0;i<output.size();i++) cout<<" "<<output[i];
cout<<endl;
}
return 0;
}
剩下的就是floyd判通 , 然后稍稍修改代码就可以啦