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的更多相关文章

  1. 100211D Police Cities

    传送门 分析 看到这个题我们的第一反应自然是Tarjan缩点,在这之后我们可以发现实际只要在缩点之后所有出度或入度为0的点布置警察局就可以达到要求,我们用dpij表示考虑前i个出度或入度为0的点共布置 ...

  2. 【ZOJ 3200】Police and Thief

    ZOJ 3200 首先我写了个高斯消元,但是消出来了一些奇怪的东西,我就放弃了... 然后只好考虑dp:\(dp[i][j][k]\)表示走到了第i步,到了\((j,k)\)这个节点的概率. 那么答案 ...

  3. 【转载】图论 500题——主要为hdu/poj/zoj

    转自——http://blog.csdn.net/qwe20060514/article/details/8112550 =============================以下是最小生成树+并 ...

  4. 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 ...

  5. ZOJ 3794 Greedy Driver

    两次SPFA 第一关找:从1没有出发点到另一个点的多少是留给油箱 把边反过来再找一遍:重每一个点到终点最少须要多少油 Greedy Driver Time Limit: 2 Seconds       ...

  6. ZOJ 1203 Swordfish 旗鱼 最小生成树,Kruskal算法

    主题链接:problemId=203" target="_blank">ZOJ 1203 Swordfish 旗鱼 Swordfish Time Limit: 2 ...

  7. 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 ...

  8. 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 ...

  9. zoj 3747 递推dp

    Attack on Titans Time Limit: 2 Seconds      Memory Limit: 65536 KB Over centuries ago, mankind faced ...

随机推荐

  1. c# 删除程序占用的文件,强力删除文件,彻底删除文件,解除文件占用

    c# 删除程序占用的文件.清理删除文件.彻底删除文件,解除文件占用 文件打开时,以共享读写模式打开 FileStream inputStream = new FileStream(name, File ...

  2. hdu 4768 异或运算

    http://acm.hdu.edu.cn/showproblem.php?pid=4768 貌似非常多人是用的二分 可是更好的做法貌似还是异或 对于第k个人.假设他接到偶数个传单.那么异或的结果还是 ...

  3. 转:Java 计算2个时间相差多少年,多少个月,多少天的几种方式

    日期比较对象 DayCompare 代码用到了  lombok ,如果不用,其实就是把getter / setter方法自己写一遍,还有构造方法. @Data @Builder public stat ...

  4. Codeforces Round #276 (Div. 1)B. Maximum Value 筛法

    D. Maximum Value     You are given a sequence a consisting of n integers. Find the maximum possible ...

  5. FreeBSD内核之中的一个 ALQ机制的使用

    背景: 笔者由于一个项目,这段时间在使用FreeBSD进行内核模块的编程. 之前做过一段时间的Linux下驱动模块编程.对Linux下的模块编程还算熟悉. 如今突然转到FreeBSD下.尽管Linux ...

  6. How to use shared model by git in sql source control of red gate

    1.clone the git repository for datbase 2.open sql source control window and select the target databa ...

  7. 通过命令行升级git for windows

    git update-git-for-windows 配置了正确的代理,就可以通过命令行直接升级.最好是可以访问谷歌的代理,否则国内的网络通过命令行升级,下载到一半,就会失败.

  8. java输出双引号

    java输出双引号 直接看例子 //输出双引号 public class Test { public static void main(String[] args) { System.out.prin ...

  9. C++_homework_StackSort

    顾名思义(?)类似于单调栈?维护一个单调递减的栈.一旦准备入栈的元素大于栈顶元素,栈一直弹出直到准备入栈的元素小于等于栈顶元素,弹出的元素压入另一个tmp栈中. #include <iostre ...

  10. Beauty Contest(凸包求最远点)

    http://poj.org/problem?id=2187 题意:求凸包上最远点距离的平方 思路:开始用旋转卡壳求的最远点,WA,改了好久..后来又改成枚举凸包上的点..AC了.. #include ...