bzoj2788: [Poi2012]Festival

传送门

前置芝士:

关于差分约束的建图方法(口胡)

1、

  对于 x>=y+a

  y->x 连a的边

  跑最长路,可求最小值

2、

  对于x<=y+a

  y->x连a的边

  最短路,可求最大值

对于此题,x+1=y拆成 x+1>=y和x+1<=y

x->y连1的边,y->x连-1的边,如果存在负环(floyd后dis[i][i]<0)则无解(无解->存在一个权值不为0的环->一定存在一个正环一个负环)

tarjan缩点,不同强连通分量之间互不影响。

对于一个强连通分量里的点,两两之间的最短路的最大值即答案。(设这个联通分量中最大数为x,最小数为y, x<=y+dis[x][y],存在路径=dis[x][y],边权均为{0,-1,1},故此时ans=x-y+1有最大值dis[x][y]+1)

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<cmath>
 10 #include<set>
 11 #include<map>
 12 #define Formylove return 0
 13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 15 const int N=607,M=100007;
 16 typedef long long LL;
 17 typedef double db;
 18 using namespace std;
 19 int n,m1,m2;
 20 int f[N][N];
 21 
 22 template<typename T>void read(T &x)  {
 23     char ch=getchar(); x=0; T f=1;
 24     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 25     if(ch=='-') f=-1,ch=getchar();
 26     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 27 }
 28 
 29 int ecnt,fir[N],nxt[M<<1],to[M<<1];
 30 void add(int u,int v) {
 31     nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
 32 }
 33 
 34 vector<int>vc[N];
 35 int dfn[N],low[N],dfk,sta[N],top,bl[N],tot;
 36 void tarjan(int x) {
 37     dfn[x]=low[x]=++dfk;
 38     sta[++top]=x;
 39     for(int i=fir[x];i;i=nxt[i]) {
 40         if(!dfn[to[i]]) {
 41             tarjan(to[i]);
 42             low[x]=min(low[x],low[to[i]]);
 43         }
 44         else if(!bl[to[i]]) low[x]=min(low[x],dfn[to[i]]);
 45     }
 46     if(dfn[x]==low[x]) {
 47         bl[x]=++tot;
 48         for(;;) {
 49             int u=sta[top--];
 50             vc[tot].push_back(u);
 51             bl[u]=tot;
 52             if(u==x) break;
 53         }
 54     }
 55 }
 56 
 57 //#define ANS
 58 int main() {
 59 #ifdef ANS
 60     freopen("1.in","r",stdin);
 61     //freopen("1.out","w",stdout);
 62 #endif
 63     read(n); read(m1); read(m2);
 64     memset(f,127/3,sizeof(f));
 65     For(i,1,n) f[i][i]=0;
 66     For(i,1,m1) {
 67         int x,y;
 68         read(x); read(y);
 69         add(x,y);
 70         add(y,x);
 71         f[x][y]=min(f[x][y],1);
 72         f[y][x]=min(f[y][x],-1);    
 73     }
 74     For(i,1,m2) {
 75         int x,y;
 76         read(x); read(y);
 77         add(y,x);
 78         f[y][x]=min(f[y][x],0);
 79     }
 80     For(k,1,n) For(i,1,n) For(j,1,n) 
 81         f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
 82     For(i,1,n) if(f[i][i]<0) {
 83         puts("NIE");
 84         return 0;
 85     }
 86     For(i,1,n) if(!dfn[i]) tarjan(i);
 87     int ans=0;
 88     For(i,1,tot) {
 89         int up=vc[i].size();
 90         int mx=0;
 91         For(j,0,up-1) For(k,0,up-1) 
 92             mx=max(mx,f[vc[i][j]][vc[i][k]]);
 93         ans+=mx+1;
 94     }
 95     printf("%d
",ans);
 96     Formylove;
 97 }
 98 /*
 99 4 2 2
100 1 2
101 3 4
102 1 4
103 3 1
104 */
View Code
原文地址:https://www.cnblogs.com/Achenchen/p/9556397.html