标签:
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:
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个
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 #define MAXN 100 6 struct HP { 7 int len,s[MAXN]; 8 HP() { 9 memset(s,0,sizeof(s)); 10 len=1; 11 } 12 HP operator =(const char *num) { //字符串赋值 13 len=strlen(num); 14 for(int i=0; i<len; i++) s[i]=num[len-i-1]-‘0‘; 15 } 16 17 HP operator =(int num) { //int 赋值 18 char s[MAXN]; 19 sprintf(s,"%d",num); 20 *this=s; 21 return *this; 22 } 23 24 HP(int num) { 25 *this=num; 26 } 27 28 HP(const char*num) { 29 *this=num; 30 } 31 32 string str()const { //转化成string 33 string res=""; 34 for(int i=0; i<len; i++) res=(char)(s[i]+‘0‘)+res; 35 if(res=="") res="0"; 36 return res; 37 } 38 39 HP operator +(const HP& b) const { 40 HP c; 41 c.len=0; 42 for(int i=0,g=0; g||i<max(len,b.len); i++) { 43 int x=g; 44 if(i<len) x+=s[i]; 45 if(i<b.len) x+=b.s[i]; 46 c.s[c.len++]=x%10; 47 g=x/10; 48 } 49 return c; 50 } 51 void clean() { 52 while(len > 1 && !s[len-1]) len--; 53 } 54 55 HP operator *(const HP& b) { 56 HP c; 57 c.len=len+b.len; 58 for(int i=0; i<len; i++) 59 for(int j=0; j<b.len; j++) 60 c.s[i+j]+=s[i]*b.s[j]; 61 for(int i=0; i<c.len-1; i++) { 62 c.s[i+1]+=c.s[i]/10; 63 c.s[i]%=10; 64 } 65 c.clean(); 66 return c; 67 } 68 69 HP operator - (const HP& b) { 70 HP c; 71 c.len = 0; 72 for(int i=0,g=0; i<len; i++) { 73 int x=s[i]-g; 74 if(i<b.len) x-=b.s[i]; 75 if(x>=0) g=0; 76 else { 77 g=1; 78 x+=10; 79 } 80 c.s[c.len++]=x; 81 } 82 c.clean(); 83 return c; 84 } 85 HP operator / (const HP &b) { 86 HP c, f = 0; 87 for(int i = len-1; i >= 0; i--) { 88 f = f*10; 89 f.s[0] = s[i]; 90 while(f>=b) { 91 f =f-b; 92 c.s[i]++; 93 } 94 } 95 c.len = len; 96 c.clean(); 97 return c; 98 } 99 HP operator % (const HP &b) { 100 HP r = *this / b; 101 r = *this - r*b; 102 return r; 103 } 104 105 HP operator /= (const HP &b) { 106 *this = *this / b; 107 return *this; 108 } 109 110 111 HP operator %= (const HP &b) { 112 *this = *this % b; 113 return *this; 114 } 115 116 bool operator < (const HP& b) const { 117 if(len != b.len) return len < b.len; 118 for(int i = len-1; i >= 0; i--) 119 if(s[i] != b.s[i]) return s[i] < b.s[i]; 120 return false; 121 } 122 123 bool operator > (const HP& b) const { 124 return b < *this; 125 } 126 127 bool operator <= (const HP& b) { 128 return !(b < *this); 129 } 130 131 bool operator == (const HP& b) { 132 return !(b < *this) && !(*this < b); 133 } 134 bool operator != (const HP &b) { 135 return !(*this == b); 136 } 137 HP operator += (const HP& b) { 138 *this = *this + b; 139 return *this; 140 } 141 bool operator >= (const HP &b) { 142 return *this > b || *this == b; 143 } 144 145 146 }; 147 148 istream& operator >>(istream &in, HP& x) { 149 string s; 150 in >> s; 151 x = s.c_str(); 152 return in; 153 } 154 155 ostream& operator <<(ostream &out, const HP& x) { 156 out << x.str(); 157 return out; 158 } 159 const int maxn = 105; 160 HP dp[maxn][maxn],c[maxn][maxn]; 161 void calc() { 162 for(int i = 0; i < maxn; ++i) { 163 c[i][0] = c[i][i] = 1; 164 for(int j = 1; j < i; ++j) 165 c[i][j] = c[i-1][j-1] + c[i-1][j]; 166 } 167 } 168 int low[maxn],dfn[maxn],belong[maxn],bcc_size[maxn],bcc,clk; 169 vector<int>g[maxn],x,y; 170 stack<int>stk; 171 int n,m,K,ind[maxn],outd[maxn]; 172 bool instack[maxn]; 173 void init() { 174 for(int i = 0; i < maxn; ++i) { 175 dfn[i] = belong[i] = bcc_size[i] = 0; 176 g[i].clear(); 177 instack[i] = false; 178 ind[i] = outd[i] = 0; 179 } 180 bcc = clk = 0; 181 while(!stk.empty()) stk.pop(); 182 x.clear(); 183 y.clear(); 184 } 185 void tarjan(int u) { 186 dfn[u] = low[u] = ++clk; 187 stk.push(u); 188 instack[u] = true; 189 for(int i = g[u].size() - 1; i >= 0; --i) { 190 if(!dfn[g[u][i]]) { 191 tarjan(g[u][i]); 192 low[u] = min(low[u],low[g[u][i]]); 193 } else if(instack[g[u][i]]) low[u] = min(low[u],dfn[g[u][i]]); 194 } 195 if(low[u] == dfn[u]) { 196 bcc++; 197 int v; 198 do { 199 v = stk.top(); 200 stk.pop(); 201 belong[v] = bcc; 202 bcc_size[bcc]++; 203 instack[v] = false; 204 } while(v != u); 205 } 206 } 207 int main() { 208 calc(); 209 int u,v; 210 while(~scanf("%d%d%d",&n,&m,&K)) { 211 init(); 212 memset(dp,0,sizeof dp); 213 for(int i = 0; i < m; ++i) { 214 scanf("%d%d",&u,&v); 215 g[u].push_back(v); 216 } 217 dp[0][0] = 1; 218 for(int i = 1; i <= n; ++i) 219 if(!dfn[i]) tarjan(i); 220 for(int i = 1; i <= n; ++i) { 221 for(int j = g[i].size()-1; j >= 0; --j) { 222 if(belong[i] == belong[g[i][j]]) continue; 223 ind[belong[g[i][j]]]++; 224 outd[belong[i]]++; 225 } 226 } 227 for(int i = 1; i <= bcc; ++i) 228 if(!ind[i] || !outd[i]) x.push_back(i); 229 else y.push_back(i); 230 for(int i = 1; i <= x.size(); ++i) 231 for(int j = 1; j <= K; ++j) 232 for(int k = j-1; k >= 0 && j - k <= bcc_size[x[i-1]]; --k) 233 dp[i][j] += dp[i-1][k]*c[bcc_size[x[i-1]]][j - k]; 234 for(int i = x.size()+1,t = 0; i <= bcc; ++i,++t) 235 for(int j = x.size(); j <= K; ++j) 236 for(int k = x.size(); k <= j; ++k) 237 dp[i][j] += dp[i-1][k]*c[bcc_size[y[t]]][j - k]; 238 cout<<dp[bcc][K]<<endl<<endl; 239 } 240 return 0; 241 }
标签:
原文地址:http://www.cnblogs.com/crackpotisback/p/4780666.html