基本思路:
只考虑1,3,5的情况,绕后Tarjan缩点。
再考虑2,4的情况,并重构图。
最后拓扑排序,并检查是否为DAG。
若为,则输出答案,否则输出-1;
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node{
ll root,add;
};
ll n,k;
ll dfn[100010],tot=0;
bool instack[100010];
ll low[100010];
ll co[100010],col=0;
stack<ll>stk;
vector<node>v[100010];
vector<node>p[100010];
ll x[100010],y[100010],z[100010];
ll top_scc[100010];
ll of_scc[100010];
ll cnt;
ll na[100010];
ll rd[100010];
ll dp[100010];
ll cnt_scc[100010];
queue<node>q;
ll used=0;
void Tarjan(ll u) {
dfn[u]=++tot;
low[u]=dfn[u];
stk.push(u);
instack[u]=true;
for(ll e=0;e<v[u].size();e++){
ll vr=v[u][e].root;
if(!dfn[vr]){
Tarjan(vr);
low[u]=min(low[u],low[vr]);
}else if(instack[vr]){
low[u]=min(low[u],dfn[vr]);
}
}
if(low[u]==dfn[u]){
++col;
co[u]=col;
top_scc[col]=u;
cnt++;
na[u]=u;
cnt_scc[col]=1;
of_scc[u]=col;
while(stk.top()!=u)na[stk.top()]=u,co[stk.top()]=col,instack[stk.top()]=false,stk.pop(),cnt++,cnt_scc[col]++;
instack[u]=false;
stk.pop();
}
}
void topu(){
for(ll i=1;i<=n;i++){
if(rd[i]==0&&na[i]==i)
dp[i]=1,q.push({i,1});
else
dp[i]=0;
}
while(q.size()){
ll f=q.front().root;
q.pop();
used++;
for(ll i=0;i<p[f].size();i++){
ll rt=p[f][i].root,ad=p[f][i].add;
rd[rt]--;
dp[rt]=max(dp[rt],dp[f]+ad);
if(rd[rt]==0){
q.push({rt,dp[rt]});
}
}
}
if(used>=col){
ll ans=0;
for(ll i=1;i<=n;i++){
if(na[i]==i){
ans+=cnt_scc[of_scc[i]]*dp[i];
}
}
cout<<ans;
}
else{
cout<<-1;
}
}
signed main(){
cin>>n>>k;
for(ll i=1;i<=k;i++){
cin>>x[i]>>y[i]>>z[i];
if(x[i]==1){
v[y[i]].push_back({z[i],0});
v[z[i]].push_back({y[i],0});
}
if(x[i]==3){
v[z[i]].push_back({y[i],0});
}
if(x[i]==5){
v[y[i]].push_back({z[i],0});
}
}
while(cnt<n){
ll id;
for(ll i=1;i<=n;i++){
if(co[i]==0){
id=i;
break;
}
}
Tarjan(id);
}
for(ll i=1;i<=k;i++){
if(x[i]==1)continue;
if(x[i]==3){
if(z[i]==na[z[i]]&&na[y[i]]!=z[i])
p[z[i]].push_back({na[y[i]],0});
}
if(x[i]==5){
if(y[i]==na[y[i]]&&na[z[i]]!=y[i])
p[y[i]].push_back({na[z[i]],0});
}
if(x[i]==2){
p[na[y[i]]].push_back({na[z[i]],1});
}
if(x[i]==4){
p[na[z[i]]].push_back({na[y[i]],1});
}
}
for(ll i=1;i<=n;i++){
if(na[i]!=i)continue;
for(ll j=0;j<p[i].size();j++){
rd[p[i][j].root]++;
}
}
topu();
return 0;
}
记录