1 /*
2 题意:每一台computer都是有p部分组成,每一台机器都会对每台computer新加一些部分,删除一些部分,每一台机器每小时处理的computer的数量是固定的;给出的参数中,p个S表示对输入的p个部分的零件的要求:0表示必须没有,1表示必须有,2表示无所谓,p个D表示经过该机器后输出的p个部分零件的结果:0表示没有,1表示有;Q表示单位时间可处理的computer数量,最终求怎样安排这些机器的处理过程使得输出的效率最大;
3
4 题解:最大流
5 构图:将n台机器拆分成2*n个点,i->i+n表示当前机器i能处理的computer台数,然后将可以互相连接(即输入的p部分与输出的p部分需要相符合)的点连接,此处我用i+n连接j,表示机器i输出的computer可以由机器j处理,然后再加源点0,它的p部分的输出均为0,与1~n判断能否连接后再相连,权值为无限大,汇点的p部分输入均为1,n+1~2*n与汇点2*n+1判断后再相连,边权值为无限大;然后求源点到汇点的最大流即可。
6 */
7 #include <cstdio>
8 #include <cstring>
9
10 #define MAXN 205
11 #define inf 1000000000
12
13 int max_flow(int n,int mat[][MAXN],int source,int sink,int flow[][MAXN]){
14 int pre[MAXN],que[MAXN],d[MAXN],p,q,t,i,j;
15 if (source==sink) return inf;
16 for (i=0;i<n;i++)
17 for (j=0;j<n;flow[i][j++]=0);
18 for (;;){
19 for (i=0;i<n;pre[i++]=0);
20 pre[t=source]=source+1,d[t]=inf;
21 for (p=q=0;p<=q&&!pre[sink];t=que[p++])
22 for (i=0;i<n;i++)
23 if (!pre[i] && (j=mat[t][i]-flow[t][i]))
24 pre[que[q++]=i]=t+1,d[i]=d[t]<j?d[t]:j;
25 else if (!pre[i]&&(j=flow[i][t]))
26 pre[que[q++]=i]=-t-1,d[i]=d[t]<j?d[t]:j;
27 if (!pre[sink]) break;
28 for (i=sink;i!=source;)
29 if (pre[i]>0)
30 flow[pre[i]-1][i]+=d[sink],i=pre[i]-1;
31 else
32 flow[i][-pre[i]-1]-=d[sink],i=-pre[i]-1;
33 }
34 for (j=i=0;i<n; j+=flow[source][i++]);
35 return j;
36 }
37
38 struct node
39 {
40 int q;
41 int s[11],d[11];
42 }nodes[55];
43
44 int p;
45
46 bool match(node a, node b)
47 {
48 for(int i=0; i<p; i++)
49 if (a.d[i] != b.s[i] && b.s[i] != 2)
50 return false;
51 return true;
52 }
53
54 int main(void)
55 {
56 int n;
57 int mat[MAXN][MAXN];
58 int flow[MAXN][MAXN];
59 while (~scanf("%d%d",&p,&n))
60 {
61 memset(mat,0,sizeof(mat));
62 for(int i=1; i<=n; i++)
63 {
64 scanf("%d",&nodes[i].q);
65 mat[i][i+n] = nodes[i].q; // 拆点
66 for(int j=0; j<p; j++)
67 scanf("%d",&nodes[i].s[j]);
68 for(int j=0; j<p; j++)
69 scanf("%d",&nodes[i].d[j]);
70 }
71
72 for(int i=0; i<p; i++)
73 {
74 nodes[0].d[i] = 0;
75 nodes[n+1].s[i] = 1;
76 }
77
78 for(int i=1; i<=n; i++)
79 {
80 if (match(nodes[0],nodes[i]))
81 mat[0][i] = 10005;
82 if (match(nodes[i],nodes[n+1]))
83 mat[i+n][2*n+1] = 10005;
84 }
85 for(int i=1; i<=n; i++)
86 for(int j=1; j<=n; j++)
87 if (i != j && match(nodes[i],nodes[j]))
88 mat[i+n][j] = nodes[i].q;
89
90 printf("%d ",max_flow(2*n+2,mat,0,2*n+1,flow));
91
92 int sum = 0;
93 for(int i=1; i<=n; i++)
94 for(int j=1; j<=n; j++)
95 if (flow[i+n][j])
96 sum++;
97 printf("%d\n",sum);
98 for(int i=1; i<=n; i++)
99 for(int j=1; j<=n; j++)
100 if (flow[i+n][j] > 0)
101 printf("%d %d %d\n",i,j,flow[i+n][j]);
102 }
103 return 0;
104 }