P3530 [POI2012]FES-Festival

传送门


思路

对于第一种限制,我们连接 \((x,y)=1\)\((y,x)=-1\)

对于第二种限制,我们连接 \((x,y)=0\)

如果一个图只有第一种边,那么要么就是没有解(有环),要么答案就是点的个数

因此我们考虑将图缩成一个 DAG 来判断

如果一个强联通分量中出现负环,那么就无解

否则,最后的答案就是:每个强联通分量中的最长路之和,再加上强联通的数量

我们跑一遍 floyd,如果出现 \(dis_{i,i}<0\),说明有负环

细节见代码


代码

#include<iostream>
#include<fstream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#define LL long long
#define FOR(i, x, y) for(int i = (x); i <= (y); i++)
#define ROF(i, x, y) for(int i = (x); i >= (y); i--)
#define PFOR(i, x) for(int i = he[x]; i; i = r[i].nxt)
inline int rd()
{
    int sign = 1, re = 0; char c = getchar();
    while(c < '0' || c > '9'){if(c == '-') sign = -1; c = getchar();}
    while('0' <= c && c <= '9'){re = re * 10 + (c - '0'); c = getchar();}
    return sign * re;
}
const int INF = 1e9;
int n, m1, m2, dis[605][605];
struct Node
{
    int to, nxt, w;
}r[200005]; int he[605];
inline void Edge_add(int u, int v, int w)
{
    static int cnt = 0;
    r[++cnt] = (Node){v, he[u], w};
    he[u] = cnt;
}
int dfn[605], low[605], dcnt;
int ty[605] ,tcnt;
std::deque<int> q;
inline void dfs(int now)
{
    dfn[now] = low[now] = ++dcnt;
    q.push_back(now);
    PFOR(i, now)
    {
        int to = r[i].to;
        if(!dfn[to])
            dfs(to),
            low[now] = std::min(low[now], low[to]);
        else if(!ty[to]) low[now] = std::min(low[now], dfn[to]);
    }
    if(dfn[now] == low[now])
    {
        ty[now] = ++tcnt;
        while(q.back() != now)
        {
            ty[q.back()] = tcnt;
            q.pop_back();
        }
        q.pop_back();
    }
}
int ans, Lest[605];
signed main()
{
#ifndef ONLINE_JUDGE
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    n = rd(), m1 = rd(), m2 = rd();
    FOR(i, 1, n) FOR(j, 1, n) dis[i][j] = INF;
    FOR(i, 1, n) dis[i][i] = 0;
    FOR(i, 1, m1)
    {
        int a = rd(), b = rd();
        // a + 1 == b
        Edge_add(a, b, 1), Edge_add(b, a, -1);
        dis[a][b] = 1, dis[b][a] = -1;
    }
    FOR(i, 1, m2)
    {
        int a = rd(), b = rd();
        // a <= b
        Edge_add(b, a, 0);
        if(dis[b][a] == INF) dis[b][a] = 0;
    }
    FOR(i, 1, n) if(!dfn[i]) dfs(i);
    FOR(k, 1, n) FOR(i, 1, n)
    {
        if(ty[k] != ty[i] || dis[i][k] == INF) continue;
        FOR(j, 1, n)
        {
            if(ty[i] != ty[j] || dis[k][j] == INF) continue;
            dis[i][j] = std::min(dis[i][j], dis[i][k] + dis[k][j]);
        }
    }
    FOR(i, 1, n) if(dis[i][i] < 0) return puts("NIE"), 0;
    FOR(i, 1, n) FOR(j, 1, n) if(ty[i] == ty[j])
        Lest[ty[i]] = std::max(Lest[ty[i]], dis[i][j]);
    FOR(i, 1, tcnt) ans += Lest[i];
    printf("%d", ans + tcnt);
    return 0;
}
posted @ 2022-09-22 15:35  zuytong  阅读(22)  评论(0编辑  收藏  举报