[ cf1407D ] 最短路+思維
阿新 • • 發佈:2020-09-09
E. Egor in the Republic of Dagestan
題意:n個點,m條邊的有向圖。從1號點出發到n號點。每個邊有黑白兩色,你需要對點染色,一點可以通過同色邊到達另一點,求如何對所有點染色,使1到n的最短距離最大,或者根本不能到達?
題解:從n開始倒著bfs即可。如果第一次遇到某個點,則說明在真的最短路上,為了避免走這條路,我們將該點染成和連邊相反的顏色即可。如果之後又遇到這個點則根據顏色來決定是否鬆弛,並加入佇列。
#include<bits/stdc++.h> #define ll long long #define pll pair<ll,ll> #define pii pair<int,int> #define rep(i,a,b) for(int i=a;i<=b;++i) #define per(i,a,b) for(int i=a;i>=b;--i) #define mem0(x) memset(x,0,sizeof(x)) #define meminf(x) memset(x,0x3f,sizeof(x)) #define VI vector<int> #define VL vector<ll> using namespace std; const int N = 5e5+5; int color[N], dis[N],vis[N]; vector<vector<pii>> g(N); queue<int> q; int main(){ ios::sync_with_stdio(0); int n,m;cin>>n>>m; rep(i,1,m){ int u,v,t; cin>>u>>v>>t; g[v].push_back({u,t}); } meminf(dis);memset(color,-1,sizeof(color)); color[n] = dis[n] = 0; q.push(n); while(!q.empty()){ int v= q.front();q.pop(); vis[v] = 1; for(auto&it :g[v]){ int u = it.first,t = it.second; if(vis[u]) continue; if(color[u]==-1){ color[u] = 1-t; }else{ if(color[u]==t&&dis[u]>dis[v]+1){ dis[u] = dis[v]+1; q.push(u); } } } } int ans; if(dis[1] == 0x3f3f3f3f){ ans = -1; }else{ ans = dis[1]; } cout<<ans<<endl; rep(i,1,n){ cout<<max(0,color[i]); } cout<<endl; }