思路:
n很小考虑暴力搜索,但16的阶乘肯定是不行的,考虑缩小搜索范围。
由题目可知,对于有关联的位置,只要确定其中一个值,其他关联值便确定了。
我们将关联在一起的所有位置称为一个关联块,我们只需暴力搜索块的状态,
对于单点块,没有限制可以取任意值,所以我们在搜索的时候跳过单点块,
在最后搜索完之后在将单点块赋值成需要的值。
亿点点小细节:
每个块有哪些点要怎么知道呢:在输入的时候建立双向边,边权为相反数。
要求块的时候,直接dfs即可。
在这里有两个关于dfs的注意点:
1.对于标记数组,若我们每次都初始化的话,时间会加一层n,可以优化。
我们可以发现对于每次搜索一个块,我们只需要知道这个点是现在这次搜到过的即可,
我们可以利用时间戳,将每次搜索记作为tol,表示这次搜索搜索过的点时间为tol。
这样就不用重置标记数组了;
2.关于搜索块的回溯需要注意,需要先dfs到底再回溯,要按照出栈的顺序回溯;
由于要回溯,所以我们将vis数组(就是1到n位置是谁)设置成vector类型,方便回溯。
又因为在搜索的时候可能会出现负值,所以将yes数组(就是存每个数是否出现,
并出现了几次)设置成map类型,要是用数组会下标越界。
搜索的时候若该点单点成块或者该点已经赋值(vis的大小不为0),我们直接dfs(p+1)。
搜索完毕后要如何判断是否合法:
1.若有位置的值超过n或者小于1不合法
2.若有的数取超过1不合法
关于如何取答案:
fff表示单点成块个数,l存的是为取到的数。若l的个数大于1,那么对于单点成块的
数就没有确定值,随便塞两个可行值表示这个点不唯一。若l的个数为1就将这个值赋值
给单点成块的点。最后如果一个点的set值不为1,那么就是不唯一。
需要剪枝,不剪枝的话会有一个样例过不了。就是在搜索块的时候如果有位置的赋值
不合法,接下来就不进行dfs即可。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
int n,m;
set<int> s[100];
unordered_map<int,int> yes;
vector<pii> v[100];
vector<int> vis[100];
int tf=0;
int col[100];
int tol=0;
int c(int x){
int res=1;
col[x]=tol;
for(auto i:v[x]){
int fi=i.first,se=i.second;
if(col[fi]==tol) continue;
int y=vis[x][vis[x].size()-1];
if(y-se<1||y-se>n) tf=1;
vis[fi].push_back(y-se);
yes[y-se]++;
col[fi]=tol;
res+=c(fi);
}
return res;
}
void rc(int x){
col[x]=tol;
for(auto i:v[x]){
int fi=i.first,se=i.second;
if(col[fi]==tol) continue;
rc(fi);
int y=vis[x][vis[x].size()-1];
vis[fi].pop_back();
yes[y-se]--;
if(yes[y-se]==0)
yes.erase(y-se);
col[fi]=tol;
}
}
void dfs(int p){
if(p==n+1){
int f=0,ff=0,fff=0;
vector<int> l;
for(int i=1;i<=n;i++){
if(vis[i].size()==0)
fff++;
if(yes.find(i)==yes.end()){
l.push_back(i);
}
}
for(auto i:yes){
if(i.first<1||i.first>n){
f=1;break;
}
if(i.second>1){
f=1;break;
}
ff++;
}
if(f||ff+fff!=n) return;
for(int i=1;i<=n;i++){
if(vis[i].size()==0){
if(l.size()>1){
s[i].insert(l[0]);
s[i].insert(l[1]);
}
else if(l.size()){
s[i].insert(l[0]);
}
}
else if(vis[i].size()){
s[i].insert(vis[i][0]);
}
}
return;
}
if(v[p].size()==0||vis[p].size()){
dfs(p+1);
return;
}
for(int i=1;i<=n;i++){
if(yes[i]!=0) continue;
vis[p].push_back(i);
yes[i]++;
tol++;
col[p]=tol;
tf=0;
c(p);
if(!tf)
dfs(p+1);
tol++;
col[p]=tol;
rc(p);
yes[i]--;
if(yes[i]==0)
yes.erase(i);
vis[p].pop_back();
}
}
void solve(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b,c;cin>>a>>b>>c;
v[a].push_back({b,c});
v[b].push_back({a,-c});
}
dfs(1);
for(int i=1;i<=n;i++){
if(s[i].size()==1)
cout<<*s[i].begin()<<' ';
else
cout<<-1<<' ';
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t=1;
// cin>>t;
while(t--){
solve();
}
}