Description
Long long ago, there was a country named Appleland. Appleland was consisted of N cities, some were connected by road, and all the roads were one way.
One day, the king of Appleland decided to set up K police station(s) in some city. The K police station(s) should satisfy the following conditions:
(1). Every city had the route to the city which had police station.
(2). Once danger occured in any city, there always existed at least one police station which can send policeman to the city.
Now, the king wanted to know the total number of different way to set up the K police station(s).
Input
The fisrt line contains three number: N(1 <= N <= 100), M(1 <= M <= 20000) and K(1 <= N <= M), which stand for number of city, number of road and number of police station each. Then M line(s) following, each contains two integer i, j, it means that there is a road from city i to city j.
Output
There is one line which contain the total number of different way.
Sample Input
6 7 3 1 2 2 3 3 1 3 4 4 5 5 6 6 5
Sample Output
15
稍作分析:
简单图论加DP,挺麻烦的。我的作法如下。
先求强连通分量,将每个分量缩点,记录下每一个入度或出度为0的分量(这些分量必须建造至少一座警察局,其它的分量随意)。
求出组合数即可,组合数求法可以用DP实现,f[i][j]为前i个点建立j个警局的组合数,
f[i][j]+=cpp[u[i]][l]*f[i-1][j-l]其中l为分配给分量i的警局数u[i]为第i的分量包含的节点数,cpp[][]为组合运算。
本题中组合数使用杨辉三角推出,但即便开long long也无法存下最极端情况(幸运的是,数据没有卡100C50,逃过一劫)。
上代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <malloc.h> 4 #define len (struct obj*)malloc(sizeof(struct obj)) 5 6 typedef long long lll; 7 8 int min(int a,int b){ 9 if (a<b)return a; 10 return b; 11 } 12 13 int max(int a,int b){ 14 if (a>b)return a; 15 return b; 16 } 17 18 int s[101],ls; 19 int u[101],lu; 20 int time,n; 21 22 struct obj{ 23 int a; 24 struct obj*next; 25 }; 26 27 typedef struct abj{ 28 int d,p,c,po; 29 int center,num; 30 struct obj*head; 31 struct obj*til; 32 }ll; 33 34 struct road{ 35 int d; 36 int r; 37 } r[20001]; 38 39 ll a[101]; 40 lll f[101][101]; 41 42 void tarjan(int n){ 43 int t; 44 a[n].d=a[n].p=++time; 45 s[ls++]=n; 46 a[n].c=1; 47 struct obj*tp=a[n].head->next; 48 while(tp!=NULL){ 49 if (!a[tp->a].c){ 50 tarjan(tp->a); 51 a[n].p=min(a[n].p,a[tp->a].p); 52 } 53 else if (a[tp->a].c==1){ 54 a[n].p=min(a[n].p,a[tp->a].d); 55 } 56 tp=tp->next; 57 } 58 if (a[n].d==a[n].p){ 59 a[n].num=0; 60 do{ 61 t=s[--ls]; 62 a[t].c=2; 63 a[t].center=n; 64 a[n].num++; 65 }while(t!=n); 66 a[n].po=0; 67 } 68 } 69 70 void tarjan_main(){ 71 time=0; 72 for (int i=1;i<=n;i++) 73 if (!a[i].c) 74 tarjan(i); 75 } 76 77 lll cpp[101][101]; 78 79 int main(){ 80 int l,i,j,m,k; 81 scanf("%d %d %d",&n,&m,&k); 82 for (i=1;i<=n;i++){ 83 a[i].c=0; 84 a[i].po=-1; 85 a[i].til=(a[i].head=len); 86 a[i].til->next=NULL; 87 } 88 for (i=1;i<=m;i++){ 89 scanf("%d %d",&r[i].d,&r[i].r); 90 a[r[i].d].til->next=len; 91 a[r[i].d].til=a[r[i].d].til->next; 92 a[r[i].d].til->a=r[i].r; 93 a[r[i].d].til->next=NULL; 94 } 95 tarjan_main(); 96 for (i=1;i<=m;i++){ 97 if (a[r[i].d].center!=a[r[i].r].center){ 98 a[a[r[i].d].center].po|=2; 99 a[a[r[i].r].center].po|=1; 100 } 101 } 102 lu=0; 103 cpp[0][0]=1; 104 for (i=1;i<=100;i++){ 105 cpp[i][0]=1; 106 cpp[i][i]=1; 107 for (j=1;j<i;j++)cpp[i][j]=cpp[i-1][j-1]+cpp[i-1][j]; 108 } 109 int sum=n; 110 for (i=1;i<=n;i++) 111 if (a[i].po==1||a[i].po==2||a[i].po==0){ 112 sum-=a[i].num; 113 u[lu++]=a[i].num; 114 } 115 memset(f,0,sizeof(f)); 116 for (i=1;i<=k;i++) 117 if (sum+u[0]>=i){ 118 for (j=max(1,i-sum);j<=u[0]&&(i-j)<=sum&&j<=i;j++) 119 f[1][i]+=cpp[sum][i-j]*cpp[u[0]][j]; 120 } 121 for (i=2;i<=lu;i++) 122 for (j=k;j>=i;j--){ 123 for (l=1;j-l>=i-1&&l<=u[i-1];l++) 124 f[i][j]+=cpp[u[i-1]][l]*f[i-1][j-l]; 125 } 126 printf("%lld\n",f[lu][k]); 127 return 0; 128 }