ZOJ 2699 Police Cities
Police Cities
Time Limit: 10 Seconds Memory Limit: 32768 KB
Once upon the time there lived a king and he had a big kingdom. And there were n cities in his kingdom and some of them were connected by the roads. And the roads were all one-way because it would be dangerous if two carriages riding in opposite directions met on a road.
And once the king decided that he would like to establish police in his country and ordered to build police stations in some cities. But since his finances are limited, he would only like build police stations in k different cities. He would like to build them in such a way, that the following conditions were satisfied:
- it is possible to get by the roads from each city to some city with the police station;
- it is possible to get by the roads to each city from some city with the police station.
Now the king wants to know how many different ways are there to do so. Help him to find the answer to this question.
Input
There are mutilple cases in the input file.
The first line of each case contains n , m and k --- the number of cities and roads in the kingdom, and the number of police stations to build, respectively (1 <= n <= 100 , 0 <= m <= 20,000 , 1 <= k <= n ). The following m lines contain two city numbers each and describe roads, remember that it is only possible to travel along roads in one direction --- from the first city to the second one. Two cities may be connected by more than one road.
There is an empty line after each case.
Output
Output the only integer number --- the number of ways to fulfil king's request.
There should be an empty line after each case.
Sample Input
- 6 7 3
- 1 2
- 2 3
- 3 1
- 3 4
- 4 5
- 5 6
- 6 5
Sample Output
- 15
Source: Andrew Stankevich's Contest #9
解题:强连通分量缩点后进行dp
首先是入度为0或者出度为0的点必须安排那个警察,dp[i][j]表示前i个入度或者出度为0的强连通分量安排了j个警察
那么有转移方程 $dp[i][j] = \sum_{k = 0}^{k < j} dp[i-1][k]*c[x][j-k]$ 这些分量是必须至少要安置一个警司的,x表示该分量内点的数量
至于其余的,至少安放0个
- #include<bits/stdc++.h>
- using namespace std;
- #define MAXN 100
- struct HP {
- int len,s[MAXN];
- HP() {
- memset(s,,sizeof(s));
- len=;
- }
- HP operator =(const char *num) { //字符串赋值
- len=strlen(num);
- for(int i=; i<len; i++) s[i]=num[len-i-]-'';
- }
- HP operator =(int num) { //int 赋值
- char s[MAXN];
- sprintf(s,"%d",num);
- *this=s;
- return *this;
- }
- HP(int num) {
- *this=num;
- }
- HP(const char*num) {
- *this=num;
- }
- string str()const { //转化成string
- string res="";
- for(int i=; i<len; i++) res=(char)(s[i]+'')+res;
- if(res=="") res="";
- return res;
- }
- HP operator +(const HP& b) const {
- HP c;
- c.len=;
- for(int i=,g=; g||i<max(len,b.len); i++) {
- int x=g;
- if(i<len) x+=s[i];
- if(i<b.len) x+=b.s[i];
- c.s[c.len++]=x%;
- g=x/;
- }
- return c;
- }
- void clean() {
- while(len > && !s[len-]) len--;
- }
- HP operator *(const HP& b) {
- HP c;
- c.len=len+b.len;
- for(int i=; i<len; i++)
- for(int j=; j<b.len; j++)
- c.s[i+j]+=s[i]*b.s[j];
- for(int i=; i<c.len-; i++) {
- c.s[i+]+=c.s[i]/;
- c.s[i]%=;
- }
- c.clean();
- return c;
- }
- HP operator - (const HP& b) {
- HP c;
- c.len = ;
- for(int i=,g=; i<len; i++) {
- int x=s[i]-g;
- if(i<b.len) x-=b.s[i];
- if(x>=) g=;
- else {
- g=;
- x+=;
- }
- c.s[c.len++]=x;
- }
- c.clean();
- return c;
- }
- HP operator / (const HP &b) {
- HP c, f = ;
- for(int i = len-; i >= ; i--) {
- f = f*;
- f.s[] = s[i];
- while(f>=b) {
- f =f-b;
- c.s[i]++;
- }
- }
- c.len = len;
- c.clean();
- return c;
- }
- HP operator % (const HP &b) {
- HP r = *this / b;
- r = *this - r*b;
- return r;
- }
- HP operator /= (const HP &b) {
- *this = *this / b;
- return *this;
- }
- HP operator %= (const HP &b) {
- *this = *this % b;
- return *this;
- }
- bool operator < (const HP& b) const {
- if(len != b.len) return len < b.len;
- for(int i = len-; i >= ; i--)
- if(s[i] != b.s[i]) return s[i] < b.s[i];
- return false;
- }
- bool operator > (const HP& b) const {
- return b < *this;
- }
- bool operator <= (const HP& b) {
- return !(b < *this);
- }
- bool operator == (const HP& b) {
- return !(b < *this) && !(*this < b);
- }
- bool operator != (const HP &b) {
- return !(*this == b);
- }
- HP operator += (const HP& b) {
- *this = *this + b;
- return *this;
- }
- bool operator >= (const HP &b) {
- return *this > b || *this == b;
- }
- };
- istream& operator >>(istream &in, HP& x) {
- string s;
- in >> s;
- x = s.c_str();
- return in;
- }
- ostream& operator <<(ostream &out, const HP& x) {
- out << x.str();
- return out;
- }
- const int maxn = ;
- HP dp[maxn][maxn],c[maxn][maxn];
- void calc() {
- for(int i = ; i < maxn; ++i) {
- c[i][] = c[i][i] = ;
- for(int j = ; j < i; ++j)
- c[i][j] = c[i-][j-] + c[i-][j];
- }
- }
- int low[maxn],dfn[maxn],belong[maxn],bcc_size[maxn],bcc,clk;
- vector<int>g[maxn],x,y;
- stack<int>stk;
- int n,m,K,ind[maxn],outd[maxn];
- bool instack[maxn];
- void init() {
- for(int i = ; i < maxn; ++i) {
- dfn[i] = belong[i] = bcc_size[i] = ;
- g[i].clear();
- instack[i] = false;
- ind[i] = outd[i] = ;
- }
- bcc = clk = ;
- while(!stk.empty()) stk.pop();
- x.clear();
- y.clear();
- }
- void tarjan(int u) {
- dfn[u] = low[u] = ++clk;
- stk.push(u);
- instack[u] = true;
- for(int i = g[u].size() - ; i >= ; --i) {
- if(!dfn[g[u][i]]) {
- tarjan(g[u][i]);
- low[u] = min(low[u],low[g[u][i]]);
- } else if(instack[g[u][i]]) low[u] = min(low[u],dfn[g[u][i]]);
- }
- if(low[u] == dfn[u]) {
- bcc++;
- int v;
- do {
- v = stk.top();
- stk.pop();
- belong[v] = bcc;
- bcc_size[bcc]++;
- instack[v] = false;
- } while(v != u);
- }
- }
- int main() {
- calc();
- int u,v;
- while(~scanf("%d%d%d",&n,&m,&K)) {
- init();
- memset(dp,,sizeof dp);
- for(int i = ; i < m; ++i) {
- scanf("%d%d",&u,&v);
- g[u].push_back(v);
- }
- dp[][] = ;
- for(int i = ; i <= n; ++i)
- if(!dfn[i]) tarjan(i);
- for(int i = ; i <= n; ++i) {
- for(int j = g[i].size()-; j >= ; --j) {
- if(belong[i] == belong[g[i][j]]) continue;
- ind[belong[g[i][j]]]++;
- outd[belong[i]]++;
- }
- }
- for(int i = ; i <= bcc; ++i)
- if(!ind[i] || !outd[i]) x.push_back(i);
- else y.push_back(i);
- for(int i = ; i <= x.size(); ++i)
- for(int j = ; j <= K; ++j)
- for(int k = j-; k >= && j - k <= bcc_size[x[i-]]; --k)
- dp[i][j] += dp[i-][k]*c[bcc_size[x[i-]]][j - k];
- for(int i = x.size()+,t = ; i <= bcc; ++i,++t)
- for(int j = x.size(); j <= K; ++j)
- for(int k = x.size(); k <= j; ++k)
- dp[i][j] += dp[i-][k]*c[bcc_size[y[t]]][j - k];
- cout<<dp[bcc][K]<<endl<<endl;
- }
- return ;
- }
ZOJ 2699 Police Cities的更多相关文章
- 100211D Police Cities
传送门 分析 看到这个题我们的第一反应自然是Tarjan缩点,在这之后我们可以发现实际只要在缩点之后所有出度或入度为0的点布置警察局就可以达到要求,我们用dpij表示考虑前i个出度或入度为0的点共布置 ...
- 【ZOJ 3200】Police and Thief
ZOJ 3200 首先我写了个高斯消元,但是消出来了一些奇怪的东西,我就放弃了... 然后只好考虑dp:\(dp[i][j][k]\)表示走到了第i步,到了\((j,k)\)这个节点的概率. 那么答案 ...
- 【转载】图论 500题——主要为hdu/poj/zoj
转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并 ...
- Codeforces Round #130 (Div. 2) C - Police Station 最短路+dp
题目链接: http://codeforces.com/problemset/problem/208/C C. Police Station time limit per test:2 seconds ...
- ZOJ 3794 Greedy Driver
两次SPFA 第一关找:从1没有出发点到另一个点的多少是留给油箱 把边反过来再找一遍:重每一个点到终点最少须要多少油 Greedy Driver Time Limit: 2 Seconds ...
- ZOJ 1203 Swordfish 旗鱼 最小生成树,Kruskal算法
主题链接:problemId=203" target="_blank">ZOJ 1203 Swordfish 旗鱼 Swordfish Time Limit: 2 ...
- POJ 2296 Map Labeler / ZOJ 2493 Map Labeler / HIT 2369 Map Labeler / UVAlive 2973 Map Labeler(2-sat 二分)
POJ 2296 Map Labeler / ZOJ 2493 Map Labeler / HIT 2369 Map Labeler / UVAlive 2973 Map Labeler(2-sat ...
- ZOJ 3946.Highway Project(The 13th Zhejiang Provincial Collegiate Programming Contest.K) SPFA
ZOJ Problem Set - 3946 Highway Project Time Limit: 2 Seconds Memory Limit: 65536 KB Edward, the ...
- zoj 3747 递推dp
Attack on Titans Time Limit: 2 Seconds Memory Limit: 65536 KB Over centuries ago, mankind faced ...
随机推荐
- 移动互联网App推广的十大难题
常常有朋友来问."我做了一个App,请问怎么推广啊?"或者就是"我们公司开发了一个App.想短时间内获取巨大的量."还有的就是问"有没有什么好渠道三个 ...
- tflearn中num_epoch含义就是针对所有样本的一次迭代
In tensorflow get started code: import tensorflow as tf import numpy as np features = [tf.contrib.la ...
- B5090 组题 二分答案
bzoj有毒,看不了自己哪错了...根本没法debug. 我到现在还是不知道自己代码为什么会T,二分次数也加限制了,但是还是T...救命啊!!! 题干: Description 著名出题人小Q的备忘录 ...
- 使用命名方式使用django的url模式
有如下一个url配置: urlpatterns = patterns('', (r'^archive/(\d{4})/$', archive), (r'^archive-summary/(\d{4}) ...
- web动画小结
前端写动画,无非两种方案,一种是通过css,另一种是js css的方案: 1.transform的单独使用 (IE9+) rotate(90deg) 2d旋转,也可以理解为沿着3D的Z轴旋转 rota ...
- 2013 ACM/ICPC Asia Regional Changsha Online - J
原题戳这里. 题意: 有一未知列数a1,a2,a3.....an, 已知s[i]=a[i-1]+a[i]+a[i] (1<i<n) s[1]=a[1]+a[2]; s[n]=a[n-1] ...
- yaml标记语言的简介
今天遇到yml这个文件,挺懵的.也是百度了一把. 这篇博文不错:http://www.ibm.com/developerworks/cn/xml/x-1103linrr/ 这图画得不错:http:// ...
- invoke与call
“调用一个委托实例” 中的 “调用” 对应的是invoke,理解为 “唤出” 更恰当.它和后面的 “在一个对象上调用方法” 中的 “调用” 稍有不同,后则对应的是call.在英语的语境中,invoke ...
- asp.net 正则表达式 得到图片url 得到汉字
//取图片 MatchCollection matchs = Regex.Matches(AskText,@"<img\s[^> ]*src=( ...
- 黑客常用dos命令
http://blog.csdn.net/CSDN___LYY/article/details/77802438