RT,写的是按差分约束的方法建图,然后 Tarjan 缩点、判无解,最后拓扑排序 + DP 求最短路。WA,70 分。谢谢。
#include <bits/stdc++.h>
#define int long long
using namespace std;
namespace IO
{
inline int read()
{
int f = 1, x = 0;
char c = getchar();
while(c < '0' || c > '9'){
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
x = x * 10 + c - '0';
c = getchar();
}
return f * x;
}
inline void write(int x)
{
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO;
void solve();
signed main()
{
solve();
return 0;
}
const int MAXN = 1e5;
int n, m;
vector < vector < pair < int, int > > > g(MAXN + 5);
vector < vector < pair < int, int > > > ng(MAXN + 5);
int idx, sum;
int dfn[MAXN + 5], low[MAXN + 5], clr[MAXN + 5];
bool vis[MAXN + 5];
stack < int > s;
int siz[MAXN + 5], indeg[MAXN + 5], f[MAXN + 5];
queue < int > q;
int minn, ans;
void Add(int u, int v, int w)
{
g[u].push_back(make_pair(v, w));
}
void Tarjan(int u)
{
s.push(u), vis[u] = true, dfn[u] = low[u] = ++ idx;
for(auto i : g[u]){
int v = i.first;
if(dfn[v] == 0) Tarjan(v), low[u] = min(low[u], low[v]);
else if(vis[v] == true) low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u]){
sum ++;
int v; do { v = s.top(), s.pop(), vis[v] = false, clr[v] = sum, siz[sum] ++; } while(u != v);
}
}
void solve()
{
freopen("[SCOI 2011] 糖果/P3275_8.in", "r", stdin);
n = read(), m = read();
for(int i = 1; i <= m; i ++){
int t = read(), u = read(), v = read();
if(t == 1) Add(u, v, 0), Add(v, u, 0);
if(t == 2) Add(v, u, - 1);
if(t == 3) Add(u, v, 0);
if(t == 4) Add(u, v, - 1);
if(t == 5) Add(v, u, 0);
}
for(int u = 1; u <= n; u ++) if(dfn[u] == 0) Tarjan(u);
for(int u = 1; u <= n; u ++){
for(auto i : g[u]){
int v = i.first, w = i.second;
if(clr[u] == clr[v]){
if(w == - 1){
write( - 1), putchar('\n');
return;
}else continue;
}
ng[clr[u]].push_back(make_pair(clr[v], w));
indeg[clr[v]] ++;
}
}
for(int u = 1; u <= sum; u ++) f[u] = 2e18;
for(int u = 1; u <= sum; u ++) if(indeg[u] == 0) q.push(u), f[u] = 0;
while( ! q.empty()){
int u = q.front(); q.pop();
for(auto i : ng[u]){
int v = i.first, w = i.second;
f[v] = min(f[v], f[u] + w);
if( -- indeg[v] == 0) q.push(v);
}
}
minn = 2e18;
for(int u = 1; u <= sum; u ++) minn = min(minn, f[u]);
for(int u = 1; u <= sum; u ++) ans += f[u] * siz[u];
ans -= n * (minn - 1);
write(ans), putchar('\n');
}