博客园的编辑器真的是太蛋疼了= =,想用tex然后上jpg又贴不了链接,真的很纠结啊= =

T1:[TJOI2015]线性代数

描述:戳上面吧= =

首先这道题我觉得是这套题最漂亮的一道题了(虽然说学校的题库里居然有一道和这个一模一样的= =)

首先我们可以先把那个式子转化为TJOI2015 day1解题报告其中b[i]是表示矩阵a中第i行为0或为1,然后就有两种方法转化为网络流啦

方法一:可以用最大权闭合子图的方法来考虑,将c[i]以及a[i][j]的选择与否视为事件的话,可以发现是一个点数为n*n的最大权闭合子图,就可以愉快的用网络流来搞辣

方法二:我们可以看做一个二元关系,因为可以看做i的选取会花费 c[i],而同时选择i, j则会获得一定的收益,那么我们可以得到一个二元关系(但还是需要经过一定的转化的),然后点数就只有n啦

我只写了方法一,虽说点数很多,但边数少,还是很快的

还有一种水法,貌似直接把所有a相加然后减去b就行辣(数据就是这么水= =)

CODE:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 #define maxn 300000
 7 #define maxm 900000
 8 struct edges{
 9     int to,next,cap;
10 }edge[maxm*2];
11 int next[maxn],l;
12 inline void addedge(int x,int y,int z) {
13     l++;
14     edge[l*2]=(edges){y,next[x],z};next[x]=l*2;
15     edge[l*2+1]=(edges){x,next[y],0};next[y]=l*2+1;
16 }
17 #define inf 0x7fffffff
18 int s,t,h[maxn],p[maxn],gap[maxn];
19 int sap(int u,int flow) {
20     if (u==t) return flow;
21     int cnt=0;
22     for (int i=p[u];i;i=edge[i].next) 
23         if (edge[i].cap&&h[u]==h[edge[i].to]+1) {
24             int cur=sap(edge[i].to,min(flow-cnt,edge[i].cap));
25             edge[i].cap-=cur;edge[i^1].cap+=cur;
26             p[u]=i;
27             if ((cnt+=cur)==flow) return cnt;
28         }
29     if (!(--gap[h[u]])) h[s]=t;
30     gap[++h[u]]++;
31     p[u]=next[u];
32     return cnt;
33 }
34 inline int maxflow(){
35     for (int i=1;i<=t;i++) p[i]=next[i];
36     memset(gap,0,sizeof(gap));
37     memset(h,0,sizeof(h));
38     gap[0]=t;
39     int flow=0;
40     while (h[s]<t) flow+=sap(s,inf);
41     return flow;
42 }
43 int id[510][510],cnt,n;
44 int main(){
45     freopen("algebra.in","r",stdin);
46     freopen("algebra.out","w",stdout);
47     scanf("%d",&n);
48     for (int i=0;i<=n;i++) 
49         for (int j=1;j<=n;j++) id[i][j]=++cnt;
50     s=++cnt,t=++cnt;
51     int sum=0;
52     for (int i=1;i<=n;i++) 
53         for (int j=1;j<=n;j++) {
54             int x;
55             scanf("%d",&x);
56             addedge(s,id[i][j],x);
57             sum+=x;
58         }
59     for (int i=1;i<=n;i++) {
60         int x;
61         scanf("%d",&x);
62         addedge(id[0][i],t,x);
63     }
64     for (int i=1;i<=n;i++) 
65         for (int j=1;j<=n;j++) {
66             addedge(id[i][j],id[0][i],inf);
67             addedge(id[i][j],id[0][j],inf);
68         }
69     printf("%d\n",sum-maxflow());
70     return 0;
71 }
View Code

相关文章: