测评地址
第一行给出两个整数N和M。
之后M行,每行三个整数T,A,B,表示一对恒星(A,B)之间的亮度关系。恒星的编号从1开始。
如果T=1,说明A和B亮度相等。
如果T=2,说明A的亮度小于B的亮度。
如果T=3,说明A的亮度不小于B的亮度。
如果T=4,说明A的亮度大于B的亮度。
如果T=5,说明A的亮度不大于B的亮度。
就是告诉你点之间的关系,给每个点确定边权使总和最小最小最小最小
在差分约束系统中有两种表达式
1
x[j] >= x[i] + K
在松弛后所有的点都满足以上条件
所以这个表达式建图的话是跑最长路的
每个点的上界是无穷的
下界可以通过最长路求出来
所以所有点权总和最小值 可以 用表达式1建图跑最长路求
2
x[j] <= x[i] + K
跟1式类似
这个题是存在环的
就比如 val[1] = val[2] ,val[2]=val[3] ,val[3]=val[1]
那么1 ,2 ,3 三个点就形成了一个环
环中的任意两点间不能存在大于0的边权
如果存在的话,求最长路会死循环(无解的情况)
那么每个联通块对答案的贡献就是(size×w)
接下来我们把每一个联通块看作一个单独的点在DAG上跑一边最长路就ok了
1.tarjan 缩点(假设都会建图)
2, 建图的时候建超级原点
(也可以在缩完点之后建新图的时候在建立超级原点)
3.每个点的点权最少为1
(因为有超级原点的存在,这里可以不用初始化)
4.DAG上dp求最长路
5.求解答案(每个联通块的贡献)
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const int maxn = 4e5 + 70;
int head[maxn],cntt;
struct node {
int u,v,w,next;
} e[maxn];
void add(int u,int v,int w) {
e[cntt].u=u,e[cntt].v=v,e[cntt].w=w;
e[cntt].next=head[u],head[u]=cntt++;
}
int n,m,dfn[maxn],indexx,low[maxn],vis[maxn],top,st[maxn];
int cnt,id[maxn],in[maxn],dp[maxn];;
vector<int>ne[maxn];
vector< pair<int,int> > g[maxn];
void tarjan(int u) {
dfn[u] = low[u] = ++indexx;
vis[u] =1,st[++top] = u;
for(int i=head[u]; ~i; i=e[i].next) {
int v = e[i].v;
if(!dfn[v]) 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 yy;
++cnt;
do {
yy=st[top];
vis[yy] =0 ;
id[yy]=cnt;
ne[cnt].push_back(yy);
top--;
} while(yy!=u);
}
}
void DAG() {
queue<int>q;
for(int i=1; i<=cnt; i++) if(in[i]==0) q.push(i),dp[i] = 0;
while(q.size()) {
int fr = q.front();
q.pop();
for(auto t:g[fr]) {
int v = t.first;
int w = t.second;
dp[v] = max(dp[v],dp[fr]+w);
in[v]--;
if(in[v]==0) q.push(v);
}
}
ll temp=0;
for(int i=1 ; i<=cnt ; i++) temp+=ne[i].size()*dp[i]*1ll;
cout<<temp;
}
int main() {
// ios::sync_with_stdio(false);
cin>>n>>m;
memset(head,-1,sizeof head);
for(int i=1 ; i<=n ; i++) add(0,i,1);
for(int i=1 ; i<=m ; i++) {
int op,u,v;
cin>>op>>u>>v;
if(op==1) add(u,v,0),add(v,u,0);
else if(op==2) add(u,v,1);
else if(op==3) add(v,u,0);
else if(op==4) add(v,u,1);
else if(op==5) add(u,v,0);
}
for(int i=0 ; i<=n ; i++) if(dfn[i]==0)tarjan(i);
int flag=0;
for(int i=0 ; i<=n ; i++) {
if(flag) break;
for(int j=head[i]; ~j; j=e[j].next) {
int v = e[j].v;
if(id[v]==id[i]) {
if(e[j].w>0) {
flag=1;
break;
}
} else {
g[id[i]].push_back({
id[v],e[j].w});
in[id[v]]++;
}
}
}
if(flag) cout<<"-1";
else DAG();
return 0;
}
/*
*/