[Poi2012]Festival 变态 差分约束题

题意

有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类:

1. 给出a,b (1<=a,b<=n),要求满足Xa + 1 = Xb

2. 给出c,d (1<=c,d<=n),要求满足Xc <= Xd

在满足所有限制的条件下,求集合{Xi}大小的最大值。

(自己注:求集合中不相同的的元素最多)

solution

(最后发现我tarjan写挂了......)

1.建图

Xa+1==Xb   ->   Xa+1<=Xb && Xa+1>=Xb

Xc<=Xd   ->   Xc-Xd<=0

2.floyd判负环(无解)&&求出两点之间的最短距离

初始化mp[i][j]为INF

记录下边后,把mp[i][j]=0

floyd一遍,如果mp[i][i]<0,说明存在负环   (因为自己到自己不是0,肯定是走了一个负环回来,变小了,一定有负环嘛)

3.tarjan缩点

最后的ans是所有强联通分量 max-min+1 的和

证明:

对于每一个强连通分量,把他们连起来的一定是  w=0  的边

如果不是,一定是{1,-1},但是两个点之间的边是相反关系,如果有1/-1边连强连通分量,那么一定有一条-1/1的边

就不是两个强连通分量了

而又因为边只有{0,1,-1}的边,所以从最小值~最大值一定是连续的,min又一定是0,因为有1/-1的边

所以ans=∑(max-min+1)

对于每一个强连通分量,求出最短路的最大值+1,即为此强连通分量对ans的贡献

累加起来即可

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #define mem(a,b) memset(a,b,sizeof(a))
  5 using namespace std;
  6 const int N=606;
  7 struct son
  8 {
  9     int v,next;
 10 };
 11 son a1[200066];
 12 int first[200066],e;
 13 void addbian(int u,int v)
 14 {
 15     a1[e].v=v;
 16     a1[e].next=first[u];
 17     first[u]=e++;
 18 }
 19
 20 int n,m1,m2;
 21 int u,o;
 22 int mp[N][N];
 23 int dfn[N],low[N],now,ans;
 24 int zhan[200006],he,flag[N];
 25 int ji[N],jinow;
 26
 27 void jilu()
 28 {
 29     int temp=-0x7fffffff;
 30     for(int i=1;i<=jinow;++i)
 31       for(int j=1;j<=jinow;++j)
 32       {
 33             if(mp[ji[i]][ji[j]]>temp)
 34               temp=mp[ji[i]][ji[j]];
 35         }
 36     ans+=temp+1;
 37 }
 38
 39 void tarjan(int x)
 40 {
 41     //printf("x=%d\n",x);
 42     low[x]=dfn[x]=++now;
 43     flag[x]=1;zhan[++he]=x;
 44     for(int i=first[x];i!=-1;i=a1[i].next)
 45     {
 46         int temp=a1[i].v;
 47         //cout<<temp;
 48         if(dfn[temp]==-1)
 49         {
 50             tarjan(temp);
 51             if(low[x]>low[temp])
 52               low[x]=low[temp];
 53         }
 54         else
 55           if(flag[temp])
 56             if(low[x]>dfn[temp])
 57               low[x]=dfn[temp];
 58     }
 59
 60     if(low[x]==dfn[x])
 61     {
 62         int temp;
 63         jinow=0;
 64         while(1)
 65         {
 66             temp=zhan[he--];flag[temp]=0;
 67             ji[++jinow]=temp;
 68             if(temp==x)
 69               break;
 70         }
 71         jilu();
 72     }
 73 }
 74
 75 int floyd()
 76 {
 77     int temp;
 78     for(int i=1;i<=n;++i)
 79       mp[i][i]=0;
 80     for(int k=1;k<=n;++k)
 81       for(int i=1;i<=n;++i)
 82         for(int j=1;j<=n;++j)
 83         {
 84                 temp=mp[i][k]+mp[k][j];
 85           if(mp[i][j]>temp)
 86             mp[i][j]=temp;
 87             }
 88     for(int i=1;i<=n;++i)
 89       if(mp[i][i]<0)
 90         return 0;
 91     return 1;
 92 }
 93
 94 int main(){
 95
 96     //freopen("1.txt","r",stdin);
 97
 98     mem(first,-1);
 99     mem(mp,0x3f);
100     mem(dfn,-1);
101
102     scanf("%d%d%d",&n,&m1,&m2);
103     for(int i=1;i<=m1;++i)
104     {
105         scanf("%d%d",&u,&o);
106         addbian(u,o);
107         addbian(o,u);
108         mp[u][o]=min(1,mp[u][o]);
109         mp[o][u]=min(-1,mp[o][u]);//有可能会重复
110     }
111     for(int i=1;i<=m2;++i)
112     {
113         scanf("%d%d",&u,&o);
114         addbian(o,u);
115         mp[o][u]=min(0,mp[o][u]);
116     }
117     if(floyd()==0)
118     {
119         printf("NIE\n");
120         return 0;
121     }
122 //    cout<<0;
123     for(int i=1;i<=n;++i)
124       if(dfn[i]==-1)
125         tarjan(i);
126
127     cout<<ans<<endl;
128     //while(1);
129     return 0;
130 }

code

时间: 2024-10-01 04:32:05

[Poi2012]Festival 变态 差分约束题的相关文章

hdu 差分约束题集

[HDU]1384 Intervals 基础差分约束★1529 Cashier Employment 神级差分约束★★★★ 1531 King 差分约束★1534 Schedule Problem 差分约束输出一组解★3440 House Man 比较好的差分约束★★3592 World Exhibition 简单★3666 THE MATRIX PROBLEM 中等★★4274 Spy's Work [先处理出欧拉序列,然后就是差分约束了...] [POJ]1201 Intervals1275

POJ 1364 King --差分约束第一题

题意:求给定的一组不等式是否有解,不等式要么是:SUM(Xi) (a<=i<=b) > k (1) 要么是 SUM(Xi) (a<=i<=b) < k (2) 分析:典型差分约束题,变换,令Ti = SUM(Xj) (0<=j<=i).  则表达式(1)可以看做T(a+b)-T(a-1) > k,也就是T(a-1)-T(a+b) < -k,又因为全是整数,所以T(a-1)-T(a+b) <= -k-1.  同理,(2)看做T(a+b)-T(

【转载】夜深人静写算法(四)——差分约束

[转载]夜深人静写算法(四) - 差分约束  目录     一.引例       1.一类不等式组的解   二.最短路       1.Dijkstra       2.图的存储       3.链式前向星       4.Dijkstra + 优先队列       5.Bellman-Ford       6.SPFA       7.Floyd-Warshall   三.差分约束        1.数形结合        2.三角不等式        3.解的存在性        4.最大值

[BZOJ2330]SCOI2011糖果|差分约束

差分约束题..学了一下差分约束,我觉得还是挺简单的,考虑f[u]-f[v]<=c,发现和最短路的松弛操作神似,最短路跑完之后对于一条边(v,u),显然有d[u]<=d[v]+c,不就是上面差分约束的式子吗..那就转化成最短(长)路做咯,以最短路为例了,对于每个f[u]-f[v]<=c,连一条v到u权值为c的边,然后跑最短路,如果有负环那就说明无解,没有的话跑完之后各点的d值就是解.. 对于本题,d[a]==d[b],有 d[a]-d[b]>=0, d[b]-d[a]>=0 d

Candies(差分约束_栈+SPFA)

CandiesCrawling in process... Crawling failed Time Limit:1500MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u Submit Status Description During the kindergarten days, flymouse was the monitor of his class. Occasionally the head-teacher b

ZOJ 2770 Burn the Linked Camp 差分约束+SPFA

第一道正儿八经的差分约束题 有排成一列的n个点,首先告诉你每个点的值最多是多少(最少显然要大于0),然后告诉你m段i,j,k,表示第i个点到第j个点的值的和至少有k,问你总和至少为多少. 要注意的是,告诉你的所有关系式都不要忘记建边,一开始漏了大于0的条件调半天o(╯□╰)o 不等式的形式是a-b<=c这样的= = 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <

「POJ1201」Intervals - 差分约束

->戳我进原题 *** Intervals Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 30393 Accepted: 11768 Description You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn. Write a program that: reads the number of intervals, the

「TYVJ1415」西瓜种植 - 差分约束

->戳我进原题 西瓜种植 时间限制:1000ms 空间限制:131072KiB 题目背景 笨笨:小西瓜,小西瓜~ 路人甲:不会呀,这西瓜明明就大着啊-- 笨笨:那--大西瓜,大西瓜~ 路人甲:这么快就改口了-- 笨笨:西瓜西瓜~可爱的西瓜~ 题目描述 笨笨种了一块西瓜地,但这块西瓜地的种植范围是一条直线的-- 笨笨在一番研究过后,得出了 \(m\) 个结论,这 \(m\) 个结论可以使他收获的西瓜最多. 笨笨的结论是这样的: 从西瓜地 \(B\) 处到 \(E\) 处至少要种植 \(T\) 个西

bzoj2788 festival 差分约束

填坑中--链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2788 题意: 有$n$个正整数$X1,X2,...,Xn$,再给出$m1+m2$个限制条件,限制分为两类:1. 给出$a,b(1<=a,b<=n)$,要求满足$Xa + 1 = Xb$2. 给出$c,d (1<=c,d<=n)$,要求满足$Xc <= Xd$在满足所有限制的条件下,求集合${Xi}$大小的最大值. 首先看情况我们也知道是差分约束-- 但是这个差分