明天的這個時候就在火車上了,所以這是最后一篇了,基本上算是對這次培訓的總結。
學術上的東西就不想多說。
但至少我在這次活動中認識不少新朋友,認識到了外面世界的廣大,認識到了高人的層出不窮。
我想,回去后,只能說,要抓緊時間,干好每一件要干好的事。
Day5
曹利國帶病給我們上課,于是大家甚為感動,學習熱情高漲。
“潛伏”了四天的“大牛”們開始踴躍地回答各種問題。
驟然發(fā)現,我們這里還有三個要馬上去參加冬令營的同學.......
學習了圖論的各種算法,發(fā)現一個月不做題,思維復雜度下降了。
看來以后要堅持好好學習。
晚自習花了到目前為止的所有時間透徹地研究了最大流的Dinic算法。
打破了我三次學習網絡流都失敗的悲慘境況(省賽前、同步賽前,NOIP前)
看來RP要回升了(元旦后一直都處于RP低谷中)
于是給模板起名RP_response
聲明:這個模板有問題,L的初值應該為1.(在init里面)

RP_response[Ditch 網絡最大流模板]

/**//*
USER:zyn19961
LANG:C++
TASK:ditch
*/
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=300;
const int maxm=300000;
const int Inf=0x7fffffff;

struct S
{
int to,next;
int c;
}s[maxm*2];
int level[maxn],Head[maxn],Queue[maxn],out[maxn],L;
int max_flow(int n,int S,int T);
inline void init();
inline void insert(int x,int y,int c);
int m,n;

int main()
{
freopen("ditch.in","r",stdin);
freopen("ditch.out","w",stdout);

while(scanf("%ld %ld",&m,&n)!=EOF)
{
init();

for(int i=0;i<m;i++)
{
int from,to,cost;
scanf("%ld %ld %ld",&from,&to,&cost);
insert(from,to,cost);
}
int S,T;
S=1;T=n;
printf("%ld\n",max_flow(n,S,T));
}
return 0;
}

inline void init()
{
L=0;
memset(Head,0,sizeof(Head));
}

inline void insert(int x,int y,int c)
{
L++;
s[L].to=y;
s[L].c=c;
s[L].next=Head[x];
Head[x]=L;
L++;
s[L].to=x;
s[L].c=0;
s[L].next=Head[y];
Head[y]=L;
}

int max_flow(int n,int S,int T)
{
int ret=0;
int head=1,tail=1;

while(1)
{//while 最多循環(huán)N次
//BFS分層 O(M)
for(int i=1;i<=n;i++)
level[i]=0;
head=1,tail=1;
level[S]=1;
Queue[1]=S;

while(head<=tail)
{
int t=Queue[head];
for(int p=Head[t];p;p=s[p].next)

if(s[p].c&&level[s[p].to]==0)
{
tail++;
level[s[p].to]=level[t]+1;
Queue[tail]=s[p].to;
}
head++;
}
//
if(level[T]==0)//r如果匯點不在集合中,即不可增廣,退出
break;
for(int i=1;i<=n;i++)//枚舉從i出發(fā)的邊
out[i]=Head[i];
int q=0;

while(1)
{

if(!q)
{//如果還在源點
int cur;// 前弧
for(cur=out[S];cur;cur=s[cur].next)
//找到下一個節(jié)點
if(s[cur].c&&out[s[cur].to]&&level[s[cur].to]==2)
break;

if(cur>0)
{
q++;
Queue[q]=cur;//用隊列存儲可增廣的路徑
out[S]=s[cur].next;
}
else
break;
}
int u=s[Queue[q]].to;
//

if(u==T)
{//已經走到匯點了,進行增廣 最多N次每次 O(N)
int dd=Inf;
int index=0;
for(int i=1;i<=q;i++)//找到最"窄"的邊

if(dd>s[Queue[i]].c)
{
dd=s[Queue[i]].c;
index=i;
}
ret+=dd;//可行流增加

for(int i=1;i<=q;i++)
{
s[Queue[i]].c-=dd;//正弧減去增加的流量
s[Queue[i]^1].c+=dd;//負弧減去增加的流量
}
for(int i=1;i<=q;i++)

if(s[Queue[i]].c==0)
{
q=index-1;
break;
//調整到第一個不能增廣的弧前的節(jié)點,繼續(xù)尋找增廣路,類似回溯
}
}

else
{//DFS尋找增廣路,配合while,實現非遞歸!! O(N*M)
int cur=out[u];
for(;cur;cur=s[cur].next)
if(s[cur].c&&out[s[cur].to]&&level[u]+1==level[s[cur].to])
//找到下一個可行的點
break;

if(cur)
{//找到了下一個點
q++;
Queue[q]=cur;
out[u]=s[cur].next;
}

else
{//回溯
out[u]=0;
q--;
}
}
//
}
}
return ret;
}

曹老師臨走前留下了聯系方式,想到老師三天里都一直在和我聊天,甚為感動。
若是再不進省隊,實在不好和老師聯系。