首页 > 代码库 > TJOI2015题解
TJOI2015题解
打算来做一波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 do104 begin105 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 do13 read(c[i]);14 readln;15 fillchar(inc,sizeof(inc),0);16 s:=0;17 ans:=0;18 for i:=1 to n do19 begin20 s:=0;21 for j:=1 to n do22 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 do26 for j:=1 to n do27 ans:=ans+b[i,j];28 for i:=1 to n do29 ans:=ans-c[i];30 while true do31 begin32 max:=-1;33 max1:=-1;34 for i:=1 to n do35 if (max<inc[i]) then36 begin37 max:=inc[i];38 max1:=i;39 end;40 if (max1=-1) then break;41 ans:=ans+max;42 for i:=1 to n do43 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 do11 begin12 for j:=1 to m do13 read(a[i,j]);14 readln;15 end;16 for i:=1 to n do17 for j:=m downto 1 do18 begin19 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题解
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。