【差分约束系统】【强连通分量缩点】【拓扑排序】【DAG最短路】CDOJ1638 红藕香残玉簟秋,轻解罗裳,独上兰舟。
题意: 给定n个点(点权未知)和m条信息:u的权值>=v的权值+w 求点权的极小解和极大解(无解则输出-1)
极小解即每个点的点权可能的最小值 极大解即每个点的点权可能的最大值
题解: 差分约束系统
对于val[u]>=val[v]+w 要得到极小解,v是没有受限制的,其最小值为0 而u受到v的限制,显然,val[u]的最小值就是val[v]+w
在多条件限制下,我们用v连向u边权为w的边表示每个限制条件val[u]>=val[v]+w 那么如果得到的是拓扑图,则按拓扑序求到每个点的最长路,就得到极小解
如果得到的不是拓扑图,即图中存在回路 那么如果存在回路边权和>0,则无解(成立的前提是边权都是大于等于零的)
总的来说,求极小解的做法就是,先对val[u]>=val[v]+w建立v连向u边权为w的边 对得到的图求强连通分量,将每个强连通分量缩成一个点 若存在边权和>0的强连通分量,则无解
否则在缩点后的拓扑图上,从入度为0的点出发按拓扑序求到每个点的最长路 该最长路就是每个点的最小值
不缩点直接判是否有回路,没有回路再拓扑,这样做会出错 因为会有边权和为0的强连通分量
对于求极大解,则将条件写成val[v]<=val[u]-w的形式 建立u连向v边权为-w的边,同样求强连通分量并缩点 在缩点后的拓扑图上做最短路,该最短路就是每个点的最大值
差分约束系统如果要求最优解而非合法解,并且整个图不能转化成从某个特定点出发的话。需要进行缩点+拓扑排序……往往只在边权都大于零或者都小于零的时候才成立。
因为对于多起点的情况而言,spfa判负环是失效的,互相制约的关系也很难通过添加虚拟结点来弥补。
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int us[1000010],vs[1000010],ws[1000010];
struct Edge{
int v,w;
};
vector<Edge>G[100010];
vector<int>rG[100010],tv;
bool used[100010];
int cmp[100010];
int ru[100010],f[100010],ansa[100010];
int n,m;
void AddEdge(int U,int V,int W){
G[U].push_back((Edge){V,W});
rG[V].push_back(U);
}
void dfs(int U){
used[U]=1;
for(int i=0;i<G[U].size();++i){
if(!used[G[U][i].v]){
dfs(G[U][i].v);
}
}
tv.push_back(U);
}
void rdfs(int U,int K){
used[U]=1;
cmp[U]=K;
for(int i=0;i<rG[U].size();++i){
if(!used[rG[U][i]]){
rdfs(rG[U][i],K);
}
}
}
int scc(){
memset(used,0,sizeof(used));
tv.clear();
for(int i=1;i<=n;++i){
if(!used[i]){
dfs(i);
}
}
memset(used,0,sizeof(used));
int K=0;
for(int i=tv.size()-1;i>=0;--i){
if(!used[tv[i]]){
rdfs(tv[i],++K);
}
}
return K;
}
int main(){
int x,y,z;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
scanf("%d%d%d",&us[i],&vs[i],&ws[i]);
AddEdge(vs[i],us[i],ws[i]);
}
int sccs=scc();
for(int i=1;i<=m;++i){
if(cmp[vs[i]]==cmp[us[i]] && ws[i]>0){
puts("-1");
return 0;
}
}
for(int i=1;i<=n;++i){
G[i].clear();
}
for(int i=1;i<=m;++i){
if(cmp[vs[i]]!=cmp[us[i]]){
++ru[cmp[us[i]]];
G[cmp[vs[i]]].push_back((Edge){cmp[us[i]],ws[i]});
}
}
queue<int>q;
for(int i=1;i<=sccs;++i){
if(!ru[i]){
q.push(i);
}
}
while(!q.empty()){
int U=q.front(); q.pop();
for(int i=0;i<G[U].size();++i){
f[G[U][i].v]=max(f[G[U][i].v],f[U]+G[U][i].w);
--ru[G[U][i].v];
if(!ru[G[U][i].v]){
q.push(G[U][i].v);
}
}
}
if(*max_element(f+1,f+sccs+1)>100){
puts("-1");
return 0;
}
for(int i=1;i<=n;++i){
ansa[i]=f[cmp[i]];
} for(int i=1;i<=n;++i){
G[i].clear();
rG[i].clear();
}
for(int i=1;i<=m;++i){
AddEdge(us[i],vs[i],-ws[i]);
}
sccs=scc();
for(int i=1;i<=m;++i){
if(cmp[us[i]]==cmp[vs[i]] && ws[i]<0){
puts("-1");
return 0;
}
}
for(int i=1;i<=n;++i){
G[i].clear();
}
for(int i=1;i<=m;++i){
if(cmp[us[i]]!=cmp[vs[i]]){
++ru[cmp[vs[i]]];
G[cmp[us[i]]].push_back((Edge){cmp[vs[i]],-ws[i]});
}
}
memset(f,0x7f,sizeof(f));
for(int i=1;i<=sccs;++i){
if(!ru[i]){
q.push(i);
f[i]=100;
}
}
while(!q.empty()){
int U=q.front(); q.pop();
for(int i=0;i<G[U].size();++i){
f[G[U][i].v]=min(f[G[U][i].v],f[U]+G[U][i].w);
--ru[G[U][i].v];
if(!ru[G[U][i].v]){
q.push(G[U][i].v);
}
}
}
if(*min_element(f+1,f+sccs+1)<0){
puts("-1");
return 0;
}
for(int i=1;i<=n;++i){
printf("%d %d\n",ansa[i],f[cmp[i]]);
}
return 0;
}
【差分约束系统】【强连通分量缩点】【拓扑排序】【DAG最短路】CDOJ1638 红藕香残玉簟秋,轻解罗裳,独上兰舟。的更多相关文章
- POJ2762 Going from u to v or from v to u?(判定单连通图:强连通分量+缩点+拓扑排序)
这道题要判断一张有向图是否是单连通图,即图中是否任意两点u和v都存在u到v或v到u的路径. 方法是,找出图中所有强连通分量,强连通分量上的点肯定也是满足单连通性的,然后对强连通分量进行缩点,缩点后就变 ...
- POJ 2762 Going from u to v or from v to u? (强连通分量缩点+拓扑排序)
题目链接:http://poj.org/problem?id=2762 题意是 有t组样例,n个点m条有向边,取任意两个点u和v,问u能不能到v 或者v能不能到u,要是可以就输出Yes,否则输出No. ...
- POJ2762 Going from u to v or from v to u? 强连通分量缩点+拓扑排序
题目链接:https://vjudge.net/contest/295959#problem/I 或者 http://poj.org/problem?id=2762 题意:输入多组样例,输入n个点和m ...
- poj 2762 Going from u to v or from v to u?【强连通分量缩点+拓扑排序】
Going from u to v or from v to u? Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 15812 ...
- FFF at Valentine(强连通分量缩点+拓扑排序)
FFF at Valentine Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- BZOJ 1924 所驼门王的宝藏(强连通分量缩点+DAG最长链)
思路不是很难,因为宝藏只会在给出的n个点内有,于是只需要在这n个点里面连边,一个点如果能到达另一个点则连一条有向边, 这样用强连通分量缩点后答案就是DAG的最长链. 问题在于暴力建图是O(n^2)的, ...
- poj 2762 Going from u to v or from v to u?(强连通分量+缩点重构图+拓扑排序)
http://poj.org/problem?id=2762 Going from u to v or from v to u? Time Limit: 2000MS Memory Limit: ...
- 【强连通分量缩点】【拓扑排序】【dp预处理】CDOJ1640 花自飘零水自流,一种相思,两处闲愁。
题意: 在n个点m条边的有向图上,从1出发的回路最多经过多少个不同的点 可以在一条边上逆行一次 题解: 在同一个强连通分量中,显然可以经过当中的每一个点 因此先将强连通分量缩点,点权为强连通分量的点数 ...
- tarjan算法(强连通分量 + 强连通分量缩点 + 桥(割边) + 割点 + LCA)
这篇文章是从网络上总结各方经验 以及 自己找的一些例题的算法模板,主要是用于自己的日后的模板总结以后防失忆常看看的, 写的也是自己能看懂即可. tarjan算法的功能很强大, 可以用来求解强连通分量, ...
随机推荐
- bzoj 1406 数论
首先问题的意思就是在找出n以内的所有x^2%n=1的数,那么我们可以得到(x+1)(x-1)=y*n,那么我们知道n|(x+1)(x-1),我们设n=a*b,那么我们对于任意的a,我们满足n%a==0 ...
- SD卡spi读写流程
SD卡spi读写流程 1.SD卡的命令格式: SD卡的指令由6字节(Byte)组成,如下: Byte1:0 1 x x x x x x(命令号,由指令标志定义,如CMD39为100111即16进制0x ...
- Linux时间子系统之一:clock source(时钟源)【转】
转自:http://blog.csdn.net/droidphone/article/details/7975694 clock source用于为linux内核提供一个时间基线,如果你用linux的 ...
- 如何在苹果官网下载旧版本的Xcode
如何在苹果官网下载旧版本的Xcode 前段时间XcodeGhost事件让很多应用中招,不乏一些知名的互联网公司开发的应用.事件的起因是开发者使用了非官方的Xcode,这些Xcode带有xcodegho ...
- pypcap 安装
1.下载winpcap开发包 https://www.winpcap.org/devel.htm 下载https://github.com/pynetwork/pypcap/releases最新发布的 ...
- 《Java编程思想》阅读笔记二
Java编程思想 这是一个通过对<Java编程思想>(Think in java)进行阅读同时对java内容查漏补缺的系列.一些基础的知识不会被罗列出来,这里只会列出一些程序员经常会忽略或 ...
- 2017百度春招<度度熊买帽子的问题>
题目: 度度熊想去商场买一顶帽子,商场里有N顶帽子,有些帽子的价格可能相同.度度熊想买一顶价格第三便宜的帽子,问第三便宜的帽子价格是多少? 数组中找到第三小的数字 注意边界条件 用STL中的set来 ...
- mac系统命令行获取root权限
刚上手mac本,对系统各种操作不熟,把过程记录下来. 使用内置命令行工具时遇到权限问题,有两种方法,第一种是在每行命令之前加上sudo,例如: 第二种是直接使用roor账户,但是mac系统默认没有ro ...
- Html Css 练习
一. 取消a链接的下划线 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...
- Zookeeper 入门第一篇
转载原文地址: ZooKeeper学习总结 第一篇:ZooKeeper快速入门 ZooKeeper学习总结 第二篇:ZooKeeper深入探讨 ZooKeeper学习第一期---Zookeeper简单 ...