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个

  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 }
View Code

 

posted @ 2015-09-03 20:35  狂徒归来  阅读(219)  评论(0编辑  收藏  举报