我的思路是缩点+拓扑排序,先加上 X=1,3,5 的所有边,然后执行 Tarjan 缩点,一个强连通分量的内部每个小朋友的糖果数量一定全部相等。然后再加入 X=2,4 的所有边,走一遍拓扑排序,输出答案。
这是提交记录
有没有哪位大佬可以看看?
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
typedef pair<int,bool> PIB;//pair<node_num,allow_same>
int n,m;
int low[MAXN],dfn[MAXN],tim=0;//dfn[i]表示初次访问i点的时间戳
bool vis[MAXN];
vector<PIB> g[MAXN];
stack<int> st;//访问到某个点u的时候,栈中存储u的祖先和已经访问过的可以到达u的祖先的点
int scc[MAXN];
int cnt[MAXN];
int in_d[MAXN];
int candy[MAXN];
queue<int> q;
int dis[MAXN];
struct EDGE{
int startpoint;
int endpoint;
}edge[(MAXN<<3)+(MAXN<<1)];
struct OPERATION{
int X;
int u;
int v;
}qu[MAXN];
void Tarjan(int u){
low[u]=dfn[u]=++tim;//初次访问
st.push(u);
vis[u]=true;
for(PIB k:g[u]){
int v=k.first;
if(dfn[v]==0){//不曾访问
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]){
low[u]=min(low[u],low[v]);
}
}
if(dfn[u]==low[u]){//自成一个强连通分量
int v;
do{
v=st.top();
st.pop();
vis[v]=false;
scc[v]=u;
++cnt[u];
}while(u!=v);
}
}
void Rebuild(){
for(int i=1;i<=n;++i){
g[i].clear();
}
for(int i=1;i<=m;++i){
int X=qu[i].X,u=qu[i].u,v=qu[i].v;
u=scc[u],v=scc[v];
if(u==v){
if(X&1){
}
else{
putchar('-'),putchar('1');
exit(0);
}
}
else{
if(X&1){
if(X>>2){
g[u].emplace_back(v,true);
}
else if(X>>1){
g[v].emplace_back(u,true);
}
else{
g[u].emplace_back(v,true);
g[v].emplace_back(u,true);
}
}
else{
if(X>>2){
g[v].emplace_back(u,false);
++in_d[u];
}
else{
g[u].emplace_back(v,false);
++in_d[v];
}
}
}
}
}
long long TP(){
for(int i=1;i<=n;++i){
if(i==scc[i]&&in_d[i]==0){
q.push(i);
candy[i]=1;
}
}
while(q.size()){
int u=q.front();
q.pop();
if(vis[u]){
return -1;
}
vis[u]=true;
for(PIB k:g[u]){
int v=k.first;
if(--in_d[v]==0){
q.push(v);
}
if(k.second){
candy[v]=max(candy[v],candy[u]);
}
else{
candy[v]=max(candy[v],candy[u]+1);
}
}
}
long long ans=0;
for(int i=1;i<=n;++i){
if((!vis[i])&&(i==scc[i])){
return -1;
}
if(i==scc[i]){
ans=ans+(long long)(cnt[i])*(long long)(candy[i]);
}
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1,X,u,v;i<=m;++i){
scanf("%d%d%d",&X,&u,&v);
qu[i].u=u;
qu[i].v=v;
qu[i].X=X;
if(X&1){
if(X>>2){
g[u].emplace_back(v,true);
}
else if(X>>1){
g[v].emplace_back(u,true);
}
else{
g[u].emplace_back(v,true);
g[v].emplace_back(u,true);
}
}
}
for(int i=1;i<=n;++i){
if(dfn[i]==0){
Tarjan(i);
}
}
Rebuild();
printf("%lld",TP());
return 0;
}