码迷,mamicode.com
首页 > 其他好文 > 详细

TJOI2015题解

时间:2016-09-15 15:09:24      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:

打算来做一波TJOI2015,来写题解啦!

Day1:

T1:

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3996

首先我们对题目中的式子化简一下,得到

技术分享

于是这就成了一个最小割模型:

  • S和(i,j)连边,权值为b[i,j]
  • (i,j)和i,j分别连边,权值为inf
  • i和T连边,权值为c[i]

于是跑一下最小割就可以了;

(然而不知道发生了什么。。。最小割跑不过去。。。似乎bzoj把p党卡常数了QAQ)

(cyand神犇说他在省选的时候贪心了一发,就过了,至今找不出反例,于是我水过去了)

最小割代码如下:

  1 uses math;
  2 var s,t,n,i,j,tot,w,cnt:longint;
  3     last,pre,other,flow:array[0..2600000] of longint;
  4     l,q:array[0..3000000] of longint;
  5     ans:int64;
  6 procedure insert(a,b,c,d:longint);
  7 begin
  8   pre[tot]:=last[a];
  9   last[a]:=tot;
 10   other[tot]:=b;
 11   flow[tot]:=c;
 12   inc(tot);
 13   pre[tot]:=last[b];
 14   last[b]:=tot;
 15   other[tot]:=a;
 16   flow[tot]:=d;
 17   inc(tot);
 18 end;
 19 function bfs:boolean;
 20 var s1,t1,u,v,q1:longint;
 21 begin
 22   fillchar(q,sizeof(q),0);
 23   for i:=0 to n do
 24     l[i]:=-1;
 25   s1:=0;
 26   t1:=1;
 27   l[s]:=1;
 28   q[t1]:=s;
 29   while (s1<t1) do
 30   begin
 31     inc(s1);
 32     u:=q[s1];
 33     q1:=last[u];
 34     while (q1>=0) do
 35     begin
 36       v:=other[q1];
 37       if (flow[q1]>0) and (l[v]=-1) then
 38       begin
 39         inc(t1);
 40         q[t1]:=v;
 41         l[v]:=l[u]+1;
 42       end;
 43       q1:=pre[q1];
 44     end;
 45   end;
 46   if (l[t]=-1) then exit(false) else exit(true);
 47 end;
 48 function find(u,int:longint):longint;
 49 var w,v,q1,t1:longint;
 50 begin
 51   if (u=t) then exit(int);
 52   w:=0;
 53   q1:=last[u];
 54   while (q1>=0) and (w<int) do
 55   begin
 56     v:=other[q1];
 57     if (l[v]=l[u]+1) then
 58     begin
 59       t1:=find(v,min(flow[q1],int-w));
 60       flow[q1]:=flow[q1]-t1;
 61       flow[q1 xor 1]:=flow[q1 xor 1]+t1;
 62       w:=w+t1;
 63     end;
 64     q1:=pre[q1];
 65   end;
 66   if (w>=int) then l[u]:=-1;
 67   exit(w);
 68 end;
 69 function dinic:int64;
 70 var e:longint;
 71   ans:int64;
 72 begin
 73   ans:=0;
 74   while bfs do
 75   begin
 76     e:=find(s,maxlongint);
 77     ans:=ans+e;
 78   end;
 79   exit(ans);
 80 end;
 81 begin
 82   readln(n);
 83   s:=n*n+n+1;
 84   t:=n*n+n+2;
 85   tot:=0;
 86   for i:=0 to t do
 87     last[i]:=-1;
 88   cnt:=n;
 89   ans:=0;
 90   for i:=1 to n do
 91   begin
 92     for j:=1 to n do
 93     begin
 94       read(w);
 95       inc(cnt);
 96       insert(s,cnt,w,0);
 97       insert(cnt,i,maxlongint,0);
 98       if (i<>j) then insert(cnt,j,maxlongint,0);
 99       ans:=ans+w;
100     end;
101     readln;
102   end;
103   for i:=1 to n do
104   begin
105     read(w);
106     insert(i,t,w,0);
107   end;
108   readln;
109   n:=t;
110   writeln(ans-dinic);
111 end.
112   

贪心代码如下:

 1 var n,i,j,s,ans,max,max1:longint;
 2     b:array[0..1000,0..1000] of longint;
 3     c,inc:array[0..1000] of longint;
 4 begin
 5   readln(n);
 6   for i:=1 to n do
 7   begin
 8     for j:=1 to n do
 9         read(b[i,j]);
10     readln;
11   end;
12   for i:=1 to n do
13     read(c[i]);
14   readln;
15   fillchar(inc,sizeof(inc),0);
16   s:=0;
17   ans:=0;
18   for i:=1 to n do
19   begin
20     s:=0;
21     for j:=1 to n do
22         s:=s+b[i,j]+b[j,i];
23     inc[i]:=b[i,i]-s+c[i];
24   end;
25   for i:=1 to n do
26     for j:=1 to n do
27         ans:=ans+b[i,j];
28   for i:=1 to n do
29     ans:=ans-c[i];
30   while true do
31   begin
32     max:=-1;
33     max1:=-1;
34     for i:=1 to n do
35       if (max<inc[i]) then
36       begin
37         max:=inc[i];
38         max1:=i;
39       end;
40     if (max1=-1) then break;
41     ans:=ans+max;
42     for i:=1 to n do
43       inc[i]:=inc[i]+b[i,max1]+b[max1,i];
44     inc[max1]:=-1;
45   end;
46   writeln(ans);
47 end.
48     

T2:

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3997

本题要用一个Dilworth定理:DAG最小链覆盖=最大独立子集,

于是发现最大独立子集显然符合题目,于是直接跑DP就可以了,方程如下:

f[i,j]=max{f[i-1,j+1]+a[i,j],f[i-1,j],f[i,j+1]}

代码如下:

 1 var t,l,n,m,i,j:longint;
 2     a,f:array[0..1005,0..1005] of int64;
 3 begin
 4   readln(t);
 5   for l:=1 to t do
 6   begin
 7     readln(n,m);
 8     fillchar(a,sizeof(a),0);
 9     fillchar(f,sizeof(f),0);
10     for i:=1 to n do
11     begin
12       for j:=1 to m do
13         read(a[i,j]);
14       readln;
15     end;
16     for i:=1 to n do
17         for j:=m downto 1 do
18         begin
19           f[i,j]:=f[i-1,j+1]+a[i,j];
20           if (f[i-1,j]>f[i,j]) then f[i,j]:=f[i-1,j];
21           if (f[i,j+1]>f[i,j]) then f[i,j]:=f[i,j+1];
22         end;
23     writeln(f[n,1]);
24   end;
25 end.

 

TJOI2015题解

标签:

原文地址:http://www.cnblogs.com/Tommyr7/p/5874806.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!