竞赛图的得分序列 (SRM 717 div 1 250)
SRM 717 DIV 1 中 出了这样一道题:
竞赛图就是把一个无向完全图的边定向后得到的有向图,得分序列就是每个点的出度构成的序列。
给出一个合法的竞赛图出度序列, 要求构造出原图(原题是求(u, v)有路径的点对数,似乎有不需要构造出原图的方法)。
当时我的做法是 直接构造一个网络,跑最大流。
比赛后总觉得这个题有什么神奇的性质,于是搜了一下相关资料:
有一篇关于得分序列的论文:
http://www.sciencedirect.com/science/article/pii/0095895679900455?via%3Dihub
其中介绍了一个性质:
Landau Theorem: 竞赛图的出度序列为${s_i}$的充要条件是 对于任意的子集X,$\sum\limits_{i \in X} s_i \ge \tbinom{|X|}{2}$
1.必要性很容易证明:如果${s_i}$是竞赛图的得分序列, 对于任意一个子集X, 它的得分之和一定大于等于它内部点之间的得分和。
2.充分性证明: 大致思路是构造一个二分图然后利用Hall定理 证明完美匹配。
首先把边<i, j> (i < j) 看做左边的点。 右边部分,对于每个$s_i$ 搞出$s_i$个点(这些点记为$i$类点)。
对于左边的点<i, j> , 向右边所有的$i$类点和$j$类点各连一条边。 显然一个完美匹配 和 一个原图对应。
根据Hall定理,有完美匹配的充要条件是 对于左边任意的点集X, $|H(X)| \ge |X|$. $H(X)$是右边与$X$中的点有边相连的点的集合。
对于左边任意的点集$X$, 设集合$Y$为$X$中的边的端点的集合。 即$Y = \{ x | (x, t) \in X \ or\ (t, x) \in X \}$
根据所给的条件, 我们有 $ |X| \leq \tbinom{|Y|}{2} \leq \sum\limits_{i \in Y} s_i = |H(X)|$, 所以存在完美匹配。定理得证。
接下来我们怎么用这个定理来构造原图呢?
当然可以构造出二分图然后跑最大匹配。
我自己又YY了一种贪心做法:
大致思想是不断给边定向,但是要让得分序列满足Landau Theorem。
先将所有点按$s_i$ 从小到大排序, 考虑 $s_i$最小的那个点x, 有$n - 1 - s_i$ 条边指向它, 我们确定哪些点向它连边,让这些点的score -1. 显然贪心一下 让score 最大的$n - 1 - s_i$个点 向它连边最优。 对于其它的点, x向它们连边就好。
AC代码:
// BEGIN CUT HERE // END CUT HERE
#line 5 "ScoresSequence.cpp"
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
using namespace std;
#define N 102
const int INF = 1e9 + ; bool a[N][N];
vector<pair<int, int> > lis, tmp; class ScoresSequence
{
public:
int count(vector <int> s)
{
int n = s.size();
memset(a, , sizeof(a));
for (int i = ; i < n; ++i) a[i][i] = true; lis.clear();
for (int i = ; i < n; ++i) lis.push_back(make_pair(s[i], i)); for (int i = ; i < n - ; ++i)
{
sort(lis.begin(), lis.end());
int c = n - i - lis[].first - ;
for (int k = ; k <= c; ++k)
{
lis[n - i - k].first--;
a[lis[n - i - k].second][lis[].second] = true;
}
for (int k = ; k < n - i - c; ++k)
a[lis[].second][lis[k].second] = true;
tmp.clear();
for (int j = ; j < lis.size(); ++j) tmp.push_back(lis[j]);
lis = tmp;
}
int ans = ;
for (int k = ; k < n; ++k)
for (int i = ; i < n; ++i)
for (int j = ; j < n; ++j)
a[i][j] |= a[i][k] & a[k][j];
for (int i = ; i < n; ++i)
for (int j = ; j < n; ++j)
ans += a[i][j];
return ans;
} // BEGIN CUT HERE
public:
void run_test(int Case) { if ((Case == -) || (Case == )) test_case_0(); if ((Case == -) || (Case == )) test_case_1(); if ((Case == -) || (Case == )) test_case_2(); if ((Case == -) || (Case == )) test_case_3(); if ((Case == -) || (Case == )) test_case_4(); }
private:
template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
void test_case_0() { int Arr0[] = {, , }; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[]))); int Arg1 = ; verify_case(, Arg1, count(Arg0)); }
void test_case_1() { int Arr0[] = {, , }; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[]))); int Arg1 = ; verify_case(, Arg1, count(Arg0)); }
void test_case_2() { int Arr0[] = {, , }; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[]))); int Arg1 = ; verify_case(, Arg1, count(Arg0)); }
void test_case_3() { int Arr0[] = {, , , , , , , , , }; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[]))); int Arg1 = ; verify_case(, Arg1, count(Arg0)); }
void test_case_4() { int Arr0[] = {,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[]))); int Arg1 = ; verify_case(, Arg1, count(Arg0)); } // END CUT HERE }; // BEGIN CUT HERE
int main()
{
ScoresSequence ___test;
___test.run_test(-);
system("pause");
}
// END CUT HERE
实现方法比较暴力,大概是 O(n^2 logn)
竞赛图的得分序列 (SRM 717 div 1 250)的更多相关文章
- TopCoder SRM 596 DIV 1 250
body { font-family: Monospaced; font-size: 12pt } pre { font-family: Monospaced; font-size: 12pt } P ...
- SRM 719 Div 1 250 500
250: 题目大意: 在一个N行无限大的网格图里,每经过一个格子都要付出一定的代价.同一行的每个格子代价相同. 给出起点和终点,求从起点到终点的付出的最少代价. 思路: 最优方案肯定是从起点沿竖直方向 ...
- Topcoder SRM 661 (Div.1) 250 MissingLCM - 数论
[题意] 给你一个数N(1<=N<=10^6),要求最小的M(M>N),使得lcm(n+1,n+2,...m)=lcm(1,2,3,...,m) [思路] 手速太慢啦,等敲完代码的时 ...
- Topcoder SRM 656 (Div.1) 250 RandomPancakeStack - 概率+记忆化搜索
最近连续三次TC爆零了,,,我的心好痛. 不知怎么想的,这题把题意理解成,第一次选择j,第二次选择i后,只能从1~i-1.i+1~j找,其实还可以从j+1~n中找,只要没有被选中过就行... [题意] ...
- 【topcoder SRM 702 DIV 2 250】TestTaking
Problem Statement Recently, Alice had to take a test. The test consisted of a sequence of true/false ...
- Topcoder口胡记 SRM 562 Div 1 ~ SRM 599 Div 1
据说做TC题有助于提高知识水平? :) 传送门:https://284914869.github.io/AEoj/index.html 转载请注明链接:http://www.cnblogs.com/B ...
- TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization & Codeforces 839 E
传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相 ...
- TopCoder SRM 667 Div.2题解
概览: T1 枚举 T2 状压DP T3 DP TopCoder SRM 667 Div.2 T1 解题思路 由于数据范围很小,所以直接枚举所有点,判断是否可行.时间复杂度O(δX × δY),空间复 ...
- Topcoder SRM 648 (div.2)
第一次做TC全部通过,截图纪念一下. 终于蓝了一次,也是TC上第一次变成蓝名,下次就要做Div.1了,希望div1不要挂零..._(:зゝ∠)_ A. KitayutaMart2 万年不变的水题. # ...
随机推荐
- Windows Vista如何让梦幻桌面支持更多格式
Windows Vista 梦幻桌面(DreamScene)到底能不能支持除了Mpeg/mpg以外的格式? 很多人说梦幻桌面的视频格式有限,像AVI.RM.RMVB就不能做成梦幻桌面!也有很多朋友着急 ...
- PHP上传文件类 代码练习
类文件: <?php class upload{ protected $fileName; protected $uploadPath; protected $maxSize; protecte ...
- 正则表达式学习(PCRE)
正则表达式是一个从左到右匹配目标字符串的模式.大多数字符自身就代表一个匹配 它们自身的模式. 1.分隔符:当使用 PCRE 函数的时候,模式需要由分隔符闭合包裹.分隔符可以使任意非字母数字.非反斜线. ...
- asp 按钮 调用ajax时 会出现返回错误,尽量使用html按钮进行调用
asp 按钮 调用ajax时 会出现返回错误,尽量使用html按钮进行调用
- 【ajax+php】动态展示4级单位(省、市、县、镇)
1.本篇教程以ajax+php动态展示[省.市.县.镇]四级地区单位 2.效果图: 3.不废话,贴代码! HTML: <div class="form-group"&g ...
- Failure to transfer org.apache.maven.plugins:maven-resources-plugin:pom:2.7
导入maven项目时,pom.xml文件报错如下: Failure to transfer org.apache.maven.plugins:maven-resources-plugin:pom:2. ...
- Workshop:用Python做科学计算
Python是程序史上最流行的开源语言之一. 仅在官方包索引PyPi上就已经发布了超过10万个开源软件包,而且还有更多的项目. 在SciPy的麾下,有一个成熟的python包生态系统,可以使用Pyth ...
- SQL中intersect、union、minus和except 运算符
1.intersect运算符intersect运算符通过只包括 TABLE1 和 TABLE2 中都有的行并消除所有重复行而派生出一个结果表.当 ALL 随 INTERSECT 一起使用时 (inte ...
- simpleRNN
simpleRNN 训练集为<爱丽丝梦境>英文版txt文档,目标:根据随机给出的10个字符,生成可能的后100个字符 词向量空间生产 In [4]: INPUT_FILE = " ...
- 【HDOJ 5379】 Mahjong tree
[HDOJ 5379] Mahjong tree 往一颗树上标号 要求同一父亲节点的节点们标号连续 同一子树的节点们标号连续 问一共同拥有几种标法 画了一画 发现标号有二叉树的感觉 初始标号1~n 根 ...