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

    import java.util.ArrayList;import java.util.List; public class Test2 {    public static void main(St ...

  2. python-day3 元组(tuple),列表(list),字典(dict)

    1.元组 tuple 有序数据,元组数据不可更改,若元组中有列表,可更改元组中的列表值里的值 元组中以","分开,若只有一个值就不是元组 包含各种数据类型 索引取值:t(2,0.0 ...

  3. Java NIO Buffer说明

    Buffer 有3个重要的参数:位置(position).容量(capactiy).上限(limit) 位置(position): 写:当前缓冲区的位置,将从position的下一个位置写数据. 读: ...

  4. 第一课trie 树 POJ 2001

    最短前缀(Openjudge上抄的) 总时间限制: 1000ms 内存限制: 65536kB 描述 一个字符串的前缀是从该字符串的第一个字符起始的一个子串.例如 "carbon"的 ...

  5. System.Net.Mail 详细讲解

    http://blog.csdn.net/liyanwwww/article/details/5507498

  6. .net core2.0 中使用aspectcore实现aop

    一.新建一个web application项目 1.1.添加AspectCore.Extensions.DependencyInjection引用 二.实现AbstractInterceptorAtt ...

  7. background使用

    background-position 有两个参数,定义背景图片起始位置可选值有: center top left right bottom px % background-size 可以用 px % ...

  8. Java多线程-synchronized关键字

    进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行. 一个进程中至少有一个线程 Ja ...

  9. 【Oracle】to_char技巧

    Select to_char(sysdate,'ss') from dual;      取当前时间秒部分 Select to_char(sysdate,'mi') from dual;      取 ...

  10. dhtmlxtree动态加载节点数据的小随笔

    最近做了一个这个东西,颇有些感触,随笔记录一下自己的过程. 首先特别感谢:https://blog.csdn.net/cfl20121314/article/details/46852591,对我的帮 ...