uva 515 King
这个题目,做之前不知道什么事差束约分,看完题目上床睡觉,想了半个小时,想到了要判断一个有向图有没有负环。第二天起来再想,觉得是判断有没有环(包括负环,正环,0环),但是不确定,要真的是这样的话,要权值来干什么,直接拓扑排序就好了,然后不确定,找了解题报告瞄一下,个个都是差束约分,然后没看其他内容,直接去学差束约分,看算法导论和网上的资料看了一个小时,懂了,就写,其实就是差束约分的模板题
说说思路和题目:给你一个长度为n的序列,从下标1到n标号,然后给你m个连续的子序列,让你求和,和要大于或者小于给定的k,如果这m个不等式都能成立,就输出成功,只要有一个不成立就输出不成立。sample中第一个就是成立的,第二个不成立
然后我们先来设定一个值Xi,Xi=a1+a2+a3……+ai ; 所以输入中是给出一个下标i和长度l,连续的子序列就是 ai+(ai+1)+(ai+2)……(ai+l)
那么显然就是等于 (Xi+l)-(Xi-1) (长的连续和减去短的连续和,得到中间的部分),这样我们就构建出了差束约分里面的不等式
所以可以知道,虽然a序列标号是从1到n,但是X序列显然是从0到n标号的(想想就知道)
另外一个转化问题就是大于(小于)转化为大于等于(小于等于),因为说了所有数字都是整数所以这个转化很容易的
Xj-Xi>k 等价于 Xj-Xi >= k+1 Xj-Xi<k 等价于 Xj-Xi <= k-1 (因为都是整数所以可以这样做)
然后就是差束约分的有向图建图,这里是用了邻接表建图,可以处理掉平行边
最后一步,设置一个新源点Xn+1 (别忘了是从0到n标号的,所以只能设置n+1),和其余所有出现过的点相连,都是有向边,从Xn+1指向其他点,权值都是0
所以这样建图后,整个图一定是连通的,在没有负环的情况下一定有可行解,然后就是spfa求最短路,顺便判断负环,有负环就没有可行解,否则就有
(其实普通的差束约分问题,只要没有负环就有可行解,而且有一组的和就会有无数组)
还有,这道题就是判断有没有可行解,其实就是判断有没有负环(原来就是我昨天晚上想的那样,不过那时候不懂什么是差束约分也证明不了),由于是有向图而且是有负权那当然是spfa,spfa有bfs和dfs版本,两个都写在代码里面,按理论讲,单单判有没有负环的话dfs更好,不过这道题bfs和dfs的时间一样,都跑出了0.072,惊奇的是冲进去了第一名,是我第一次冲进去uva的第一名
多少要纪念一下啊,毕竟做了uva大半年了第一次冲进第一名(上一次最好成绩是第5名,也是spfa_dfs判负环)
不过怎么说呢…………这道还是水题,而且能算是模板题吧
邻接表+spfa判负环
#include <cstdio> #include <cstring> #include <queue> using namespace std; #define N 110 #define M 110 #define INF 0x3f3f3f3f struct edge {int u,v,w,next; }e[M+N]; //这个数组不能只开到M,因为后面要加入一个新源点n+1,与0到n的所有顶点连接一条有向边 int first[N]; int used[N]; //在输入中出现过哪些点 int vis[N],c[N]; //spfa_dfs起标记作用 int d[N]; //最短路径数组 int n,m,edgenum,s; //s是源点也就是0,edgenum是边集数组的条数void input() {memset(used,0,sizeof(used));memset(first,-1,sizeof(first));scanf("%d",&m);edgenum=0;for(int k=0; k<m; k++) //读入所有不等式,转化为边的信息,但注意边数是edgenum不是k {int i,j,w; char op[5];scanf("%d%d%s%d",&i,&j,op,&w);j+=i; i--; //得到顶点i,j,j标号一定大于iused[i]=used[j]=1; //标记出现过这些点if(!strcmp(op,"lt")) //是小于 {w--; //相当于<=w-1e[edgenum].u=i;e[edgenum].v=j;e[edgenum].w=w;e[edgenum].next=first[i];first[i]=edgenum;edgenum++;}else //大于 {w++; //相当于>=w+1e[edgenum].u=j;e[edgenum].v=i;e[edgenum].w=-w;e[edgenum].next=first[j];first[j]=edgenum;edgenum++;}}used[n+1]=1;for(int i=0; i<=n; i++) if(used[i]) //新设置一个源点0,跟所有已有的点相连 {e[edgenum].u=n+1;e[edgenum].v=i;e[edgenum].w=0;e[edgenum].next=first[n+1];first[n+1]=edgenum;edgenum++;}return ; }void print_graph() {printf("邻接表\n");for(int i=0; i<=n+1; i++) if(used[i]){printf("%d:_____________________\n",i);for(int k=first[i]; k!=-1; k=e[k].next)printf("%d\\%d\n",e[k].v,e[k].w);}printf("*********\n");printf("打印边集数组\n");for(int i=0; i<edgenum; i++)printf("%d %d %d %d\n",e[i].u,e[i].v,e[i].w,e[i].next);printf("*********\n");return ; }int spfa_dfs(int u) {vis[u]=1;for(int k=first[u]; k!=-1; k=e[k].next) //遍历顶点u的邻接表 {int v=e[k].v , w=e[k].w;if( d[u]+w < d[v]){ d[v]=d[u]+w;if(!vis[v]){if(spfa_dfs(v))return 1;}else return 1;}}vis[u]=0;return 0; } int spfa_bfs(int s) {int flag=1;queue <int> q;memset(c,0,sizeof(c)); c[s]++;memset(d,0x3f,sizeof(d)); d[s]=0;memset(vis,0,sizeof(vis)); vis[s]=1;q.push(s);while(!q.empty()){int u=q.front(); vis[u]=0; q.pop();for(int k=first[u]; k!=-1; k=e[k].next){int v=e[k].v , w=e[k].w;if(d[u]+w<d[v]){d[v]=d[u]+w;if(!vis[v]){vis[v]=1;q.push(v);c[v]++;if(c[v]>n+1)return 1; //找到负环 }}}}return 0; //没有负环 } void judge() {s=n+1; //源点memset(d,0x3f,sizeof(d)); d[s]=0;memset(vis,0,sizeof(vis));//int tmp=spfa_dfs(s); int tmp=spfa_bfs(s);//spfa的dfs版本和bfs版本都有了,都可以AC,注释掉换过来就可以了if(tmp)printf("successful conspiracy\n");elseprintf("lamentable kingdom\n");return ; } int main() {while(scanf("%d",&n) && n){input();//print_graph(); //测试函数 judge(); }return 0; }
转载于:https://www.cnblogs.com/scau20110726/archive/2012/11/29/2795153.html
uva 515 King相关推荐
- π-Algorithmist分类题目(2)
原题网站:Algorithmist,http://www.algorithmist.com/index.php/Main_Page π-Algorithmist分类题目(2) Set Theory U ...
- 提取了下刘汝佳推荐的题号...
今天闲来没事上uva oj提取了下刘汝佳推荐的acm题号,原始数据如下: Volume 0. Getting Started 10055 - Hashmat the Brave Warrior ...
- 初学者acm的练习题指南
上机练习题参考题 忘了在哪找的啦~~希望对大家有帮助呦 <!--[if !supportLists]-->1. <!--[endif]-->Programming Bas ...
- UVA 6177 The King's Ups and Downs DP
orz想了好久好久的排列组合,未果,考虑不全--DP好难啊233333 题目链接戳这里 抛开整体不考虑,我们来考虑一下第i位(k)的插入问题: 第i位>第i-1位时,插入条件为第i-1位< ...
- HDU 5643 King's Game 打表
King's Game 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5643 Description In order to remember hi ...
- hdu-5643 King's Game(打表)
题目链接: King's Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Other ...
- UVa Online Judge 工具網站
UVa Online Judge 工具網站 转自http://www.csie.ntnu.edu.tw/~u91029/uva.html Lucky貓的ACM園地,Lucky貓的 ACM 中譯題目 M ...
- UVa Problem 10205 Stack ’em Up (完美洗牌术)
// Stack 'em Up (完美洗牌术) // PC/UVa IDs: 110205/10205, Popularity: B, Success rate: average Level: 1 / ...
- UVa 109 - SCUD Busters(凸包计算)
题目来源:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=3&pa ...
最新文章
- PAT计算出2~N所有素数
- 使用jquery.qrcode生成二维码(转)
- C语言进制转换时自动扩展位?(原码、反码、补码)(打印%o、%x时会自动扩展到32位【负数先得到其十进制真实数值,再根据其真实数值得到八进制、十进制补码】)
- [leetcode]111.二叉树的最小深度
- 计算机网络 --- 网络层路由算法与路由协议
- Shiro的鉴权方式
- redis应用场景:实现简单计数器-防止刷单
- 爬虫课第一次报错总结
- 嵌入式环境搭建之zmodem
- requests-BeautifulSoup爬取美女贴吧图片
- 复杂截面抗扭惯矩计算
- 清空文本框java_Java 添加、删除Word文档中的文本框
- 2009-2012年中国网络游戏市场投资分析及前景预测报告
- 2021年9款优秀的大数据可视化BI软件
- array unshift php,php – 用于多维数组的array_unshift
- 谷歌AlphaFold近日宣称预测出地球上几乎所有蛋白质结构
- 主成分分析(principle component analysis)介绍
- 论文笔记(精读文章) - Invisible Backdoor Attack with Sample-Specific Triggers
- 简介IntelliJ IDEAD
- 【词汇辨析】Primary, main, prime and major “主要的、首要的”
热门文章
- OpenCV几何变换的实例(附完整代码)
- OpenGL绘制带有索引的矩形的实例
- QT的QSplitter类的使用
- QT的QPlaceContent类的使用
- dvi黑屏解决方法_赛博朋克2077黑梦黑屏怎么办 黑梦BUG全黑模式解决方法
- lte核心网由哪些设备组成_一整套无线智能家居,是由哪些设备组成?这份清单告诉你答案...
- 「Python」pycharm多项目虚拟环境切换
- 引入Spacy模块出错—OSError: [E941] Can‘t find model ‘en‘.
- 23-26 Python File方法、OS文件/目录方法、异常处理、内置函数
- Kettle使用_20 笛卡尔积与前一行后一行Lead Lag