懒得复制题面,戳我戳我


Question:

(因为网上找不到好的翻译,这里简单复述一下)

告诉你\(m1+m2\)个约束条件,然后要你找出\(X_1-X_n\)这些数字,求满足要求的数列中不同的数字个数最多有多少个(exp:\(1,2,3,3,2\)里面就有三个不同的数)

Solution:

  • 首先的差分约束的连边很简单
for(int i=1;i<=m1;i++){
int x,y;scanf("%d%d",&x,&y);
add(x,y,1);add(y,x,-1);be[x]=be[y]=true;
}
for(int i=1;i<=m2;i++){
int x,y;scanf("%d%d",&x,&y);
add(x,y,0);be[x]=be[y]=true;
}
  • 然后我们要知道的就是在不同的强联通分量里面的数是不会相互影响的,因为如果不再一个强联通分量中一定是连的\(0\)边,所以我们就只用把\(0\)边连向的那个强联通分量全部变大一些就可以了
  • 所以我们就可以缩点(只用求出每个点在哪个强联通分量中就可以了),如果存在某个强连通中存在正环,就一定是不能找到一组满足的数值,输出\(NIE\)就好。
  • 然后我们就在每个不同的强联通分量中求最长路,这个强联通中的最多不同数值就是最长路数值\(+1\),然后把每个强联通的贡献相加就好了
  • PS:在求每个强联通时最好每个点作为初始点进行\(SPFA\),求出这个点为初始点时的最长路,所以嘞我们应该是可以用\(Floyd\)来做的。

我觉得我的代码打的很繁琐,所以看不看也无所谓了,另外我这个代码可以优化的就是可以在最后面求值是判断正环存在,应该可以适当减低时间复杂度


Code:

//It is coded by Ning_Mew on 4.2
#include<bits/stdc++.h>
using namespace std; const int maxn=607;
const int maxm=1e5; int n,m1,m2,INF,ans=0;
bool be[maxn];
int dist[maxn],vis[maxn],TT[maxn],vs[maxn];
int head[maxn],cnt=0,dfn[maxn],low[maxn],ct=0;
int color[maxn],num_color=0,team[maxn],last=1;
bool instack[maxn];
struct Edge{
int nxt,to,dis;
}edge[maxm*2];
bool choose[maxn]; void add(int from,int to,int dis){
edge[++cnt].nxt=head[from];
edge[cnt].to=to;
edge[cnt].dis=dis;
head[from]=cnt;
} bool SPFA(int k,int ls,int num){
queue<int>Q;while(!Q.empty())Q.pop();
Q.push(k);vis[k]=ls;be[k]=false;dist[k]=0;
TT[k]=1;vs[k]=ls;
while(!Q.empty()){
int u=Q.front();Q.pop();vis[u]=ls-1;
for(int i=head[u];i!=0;i=edge[i].nxt){
int v=edge[i].to;be[v]=false; if(num==-1||color[v]==num);else continue; if(dist[v]<dist[u]+edge[i].dis){
dist[v]=dist[u]+edge[i].dis;
if(dist[v]>n)return false;
if(vis[v]!=ls){
vis[v]=ls;Q.push(v);
if(vs[v]!=ls){
vs[v]=ls; TT[v]=1;
}else{ TT[v]++; }
}
}
}
}return true;
}
void tarjan(int u){
dfn[u]=++ct;low[u]=ct;team[last]=u;last++;instack[u]=true;
for(int i=head[u];i!=0;i=edge[i].nxt){
int v=edge[i].to;
if(dfn[v]==0){tarjan(v); low[u]=min(low[u],low[v]);
}else{if(instack[v])low[u]=min(low[u],dfn[v]);}
}
int v=-100;
if(dfn[u]==low[u]){
num_color++;
do{v=team[--last];color[v]=num_color;instack[v]=false;
}while(v!=u);
}return;
}
int lls=1;
int find(int c){
int re=-0x5f,maxx=-0x5f,minn=0x5f;
for(int i=1;i<=n;i++){
if(color[i]!=c)continue;
//memset(vis,0,sizeof(vis));
memset(dist,-0x5f,sizeof(dist));
SPFA(i,++lls,color[i]);
maxx=-0x5f;minn=0x5f; //cout<<"-----"<<' '<<c<<endl;
//for(int j=1;j<=n;j++)
// cout<<j<<' '<<color[j]<<' '<<dist[j]<<endl; for(int j=1;j<=n;j++){
if(color[j]!=c)continue;
if(dist[j]==INF)continue;
maxx=max(maxx,dist[j]);
minn=min(minn,dist[j]);
}
re=max(re,maxx-minn);
//cout<<re<<endl;
}
//cout<<"ANS:"<<c<<' '<<re<<endl;
return re;
}
int main(){
scanf("%d%d%d",&n,&m1,&m2);
memset(be,false,sizeof(be));
for(int i=1;i<=m1;i++){
int x,y;scanf("%d%d",&x,&y);
add(x,y,1);add(y,x,-1);be[x]=be[y]=true;
}
for(int i=1;i<=m2;i++){
int x,y;scanf("%d%d",&x,&y);
add(x,y,0);be[x]=be[y]=true;
}
int ls=1;
memset(dist,-0x5f,sizeof(dist));
INF=dist[0];
for(int i=1;i<=n;i++){
if(be[i]){
if(SPFA(i,++ls,-1));else{printf("NIE\n");return 0;}
}
}
for(int i=1;i<=n;i++)if(dist[i]==INF)dist[i]=0;
//for(int i=1;i<=n;i++)cout<<"num:"<<i<<' '<<dist[i]<<endl;
//cout<<"SPFA finished"<<endl;
memset(dfn,0,sizeof(dfn));memset(low,0,sizeof(low));
for(int i=1;i<=n;i++){
if(dfn[i]==0)tarjan(i);
}
//for(int i=1;i<=n;i++)cout<<"num:"<<i<<' '<<color[i]<<endl;
memset(choose,false,sizeof(choose));
for(int i=1;i<=n;i++){
if(choose[ color[i] ]==true)continue;
choose[ color[i] ]=true;
int box=find(color[i]);ans+=(box+1);
//cout<<i<<' '<<color[i]<<' '<<box<<endl;
}
printf("%d\n",ans);
return 0;
}

【题解】 [POI2012]FES-Festival (差分约束)的更多相关文章

  1. [Poi2012]Festival 差分约束+tarjan

    差分约束建图,发现要在每个联通块里求最长路,600,直接O(n3) floyed #include<cstdio> #include<cstring> #include< ...

  2. bzoj 2788 [Poi2012]Festival 差分约束+tarjan+floyd

    题目大意 有n个正整数X1,X2,...,Xn,再给出m1+m2个限制条件,限制分为两类: 1.给出a,b (1<=a,b<=n),要求满足Xa + 1 = Xb 2.给出c,d (1&l ...

  3. BZOJ 3436: 小K的农场 差分约束

    题目链接: http://www.lydsy.com/JudgeOnline/problem.php?id=3436 题解: 裸的差分约束: 1.a>=b+c  ->  b<=a-c ...

  4. BZOJ-2330-[SCOI2011]糖果(差分约束)

    Description 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的 ...

  5. 【最短路·差分约束】洛谷P1250

    题目描述 一条街的一边有几座房子.因为环保原因居民想要在路边种些树.路边的地区被分割成块,并被编号成1..N.每个部分为一个单位尺寸大小并最多可种一棵树.每个居民想在门前种些树并指定了三个号码B,E, ...

  6. 【BZOJ3436】小K的农场 差分约束

    [BZOJ3436]小K的农场 Description 背景 小K是个特么喜欢玩MC的孩纸... 描述 小K在MC里面建立很多很多的农场,总共n个,以至于他自己都忘记了每个农场中种植作物的具体数量了, ...

  7. POJ3169:Layout(差分约束)

    Layout Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 15705   Accepted: 7551 题目链接:http ...

  8. hdoj--1384--Intervals(差分约束)

    Intervals Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total ...

  9. POJ1201Intervals(差分约束)

    题意 给出数轴上的n个区间[ai,bi],每个区间都是连续的int区间. 现在要在数轴上任意取一堆元素,构成一个元素集合V 要求每个区间[ai,bi]和元素集合V的交集至少有ci不同的元素 求集合V最 ...

随机推荐

  1. Java关键字(二)——native

    本篇博客我们将介绍Java中的一个关键字——native. native 关键字在 JDK 源码中很多类中都有,在 Object.java类中,其 getClass() 方法.hashCode()方法 ...

  2. 反向路径过滤——reverse path filter

    原文地址:反向路径过滤——reverse path filter 作者:pwp_cu 反向路径过滤——reverse path filter 一.原理先介绍个非对称路由的概念参考<Underst ...

  3. Linux 网络监控工具 ss

    ss命令用来显示处于活动状态的套接字信息.功能和netstat类似,但比netstat更快更高效. ss -h Usage: ss [ OPTIONS ] ss [ OPTIONS ] [ FILTE ...

  4. 20155331《网路对抗》Exp8 WEB基础实践

    20155331<网路对抗>Exp8 WEB基础实践 基础问题回答 什么是表单 表单在网页中主要负责数据采集功能.一个表单有三个基本组成部分: 表单标签,这里面包含了处理表单数据所用CGI ...

  5. Nuget包CommonServiceLocator从1.0.3升级到2.0.4时MvvmLight的ViewModelLocator初始化SimpleIoc.Default格式不匹配问题

    原文:Nuget包CommonServiceLocator从1.0.3升级到2.0.4时MvvmLight的ViewModelLocator初始化SimpleIoc.Default格式不匹配问题 把旧 ...

  6. EZ 2018 04 21 NOIP2018 模拟赛(十) -LoliconAutomaton的退役赛

    难得的一次Unrated,避免了重回1500的尴尬 其实题目都还可以,但只不过所有人T1都炸了,可能是数据的锅(假的) 而且我因为T1SB的把T2弃了,没想到是千年水题 T3莫名爆炸,然后TM的40分 ...

  7. Caffe 深度学习框架上手教程

    Caffe 深度学习框架上手教程   blink 15年1月   Caffe (CNN, deep learning) 介绍 Caffe -----------Convolution Architec ...

  8. [LOJ#2878]. 「JOISC 2014 Day2」邮戳拉力赛[括号序列dp]

    题意 题目链接 分析 如果走到了下行车站就一定会在前面的某个车站走回上行车站,可以看成是一对括号. 我们要求的就是 类似 代价最小的括号序列匹配问题,定义 f(i,j) 表示到 i 有 j 个左括号没 ...

  9. Flask学习-Flask app启动过程

    因为0.1版本整体代码大概只有350行,比较简单.所以本篇文章会以Flask 0.1版本源码为基础进行剖析Flask应用的启动过程. Flask参考资料flask,官网有一个最简单app: from ...

  10. LeetCode 4Sum (Two pointers)

    题意 Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = ...