图算法实例.docx
- 文档编号:6064565
- 上传时间:2023-01-03
- 格式:DOCX
- 页数:30
- 大小:23.83KB
图算法实例.docx
《图算法实例.docx》由会员分享,可在线阅读,更多相关《图算法实例.docx(30页珍藏版)》请在冰豆网上搜索。
图算法实例
最大流(dinic算法)
DestroyingTheGraph
TimeLimit:
2000MSMemoryLimit:
65536K
TotalSubmissions:
980Accepted:
332SpecialJudge
Description
AliceandBobplaythefollowinggame.First,AlicedrawssomedirectedgraphwithNverticesandMarcs.AfterthatBobtriestodestroyit.Inamovehemaytakeanyvertexofthegraphandremoveeitherallarcsincomingintothisvertex,orallarcsoutgoingfromthisvertex.
Aliceassignstwocoststoeachvertex:
Wi+andWi-.IfBobremovesallarcsincomingintothei-thvertexhepaysWi+dollarstoAlice,andifheremovesoutgoingarcshepaysWi-dollars.
FindoutwhatminimalsumBobneedstoremoveallarcsfromthegraph.
Input
InputfiledescribesthegraphAlicehasdrawn.ThefirstlineoftheinputfilecontainsNandM(1<=N<=100,1<=M<=5000).ThesecondlinecontainsNintegernumbersspecifyingWi+.ThethirdlinedefinesWi-inasimilarway.Allcostsarepositiveanddonotexceed106.EachofthefollowingMlinescontainstwointegersdescribingthecorrespondingarcofthegraph.Graphmaycontainloopsandparallelarcs.
Output
OnthefirstlineoftheoutputfileprintW---theminimalsumBobmusthavetoremoveallarcsfromthegraph.OnthesecondlineprintK---thenumberofmovesBobneedstodoit.AfterthatprintKlinesthatdescribeBob'smoves.Eachlinemustfirstcontainthenumberofthevertexandthen'+'or'-'character,separatedbyonespace.Character'+'meansthatBobremovesallarcsincomingintothespecifiedvertexand'-'thatBobremovesallarcsoutgoingfromthespecifiedvertex.
SampleInput
36
123
421
12
11
32
12
31
23
SampleOutput
5
3
1+
2-
2+
#include
usingnamespacestd;
constintmaxn=202;
intS,T,N,M,c[maxn][maxn],lev[maxn],x[maxn];
intstack[maxn],top,Q[maxn],f,r;
boolinput()
{
if(scanf("%d%d",&N,&M)==EOF)
{
returnfalse;
}
inti,a,b;
S=0,T=2*N+1;
for(i=0;i<=T;++i)
{
memset(c[i],0,(T+1)*sizeof(int));
}
for(i=N+1;i<=2*N;++i)
{
scanf("%d",&c[i][T]);
}
for(i=1;i<=N;++i)
{
scanf("%d",&c[S][i]);
}
for(i=0;i { scanf("%d%d",&a,&b); c[a][b+N]=INT_MAX; } returntrue; } inlineboolMakeLevel() { inti,u; memset(lev,0,(T+1)*sizeof(int)); f=r=0; Q[r++]=S; lev[S]=1; while(f { u=Q[f++]; for(i=0;i<=T;++i) { if(c[u][i]! =0&&lev[i]==0) { lev[i]=lev[u]+1; Q[r++]=i; } } } return(lev[T]! =0); } intMaxFlow() { inti,ans=0,inc,u,v; while(MakeLevel()) { top=0; stack[top++]=S; while(top>0) { u=stack[top-1]; if(u==T) { inc=INT_MAX; for(i=top-1;i>0;--i) { u=stack[i-1]; v=stack[i]; if(c[u][v] { inc=c[u][v]; } } ans+=inc; for(i=top-1;i>0;--i) { u=stack[i-1]; v=stack[i]; c[u][v]-=inc; c[v][u]+=inc; } for(top=1;;top++) { u=stack[top-1]; v=stack[top]; if(c[u][v]==0) break; } } else { for(i=1;i<=T;++i) { if(c[u][i]! =0&&lev[i]==lev[u]+1) { stack[top++]=i; break; } } if(i>T) { lev[u]=-1; --top; } } } } returnans; } voidsolve() { inti,j,num; intans=MaxFlow(); printf("%d\n",ans); num=0; for(i=1;i { if(lev[i]==0&&i<=N||lev[i]! =0&&i>N) { x[num++]=i; } } printf("%d\n",num); j=0; for(i=0;i { if(x[i]<=N) { printf("%d-\n",x[i]); } else { printf("%d+\n",x[i]-N); } } } intmain() { while(input()) { solve(); } return0; } 树的同构(pku1635) SampleInput 2 0010011101001011 010********* 010********* 0011000111010101 SampleOutput same different #include usingnamespacestd; constintmaxn=1510; constintNIL=-1; chars[2*maxn],t[2*maxn]; typedefstruct { intnum; boolvisit; intleft,next; }Edge; intidx,ra,rb,now,len; Edgee[2*maxn]; boolinput() { if(scanf("%s%s",s,t)==EOF) returnfalse; returntrue; } voidbuild(int&n,char*p) { if(idx>=len) { return; } if(p[idx]=='0') { ++now; e[now].left=e[now].next=NIL; e[now].visit=false; n=now; ++idx; build(e[n].left,p); intq=n; //while(e[q].next! =NIL) //q=e[q].next; ++idx; build(e[q].next,p); } } intGetSum(intn) { if(n==NIL) return0; /*e[n].num=1+GetSum(e[n].left);//这边表示的是树,不是二叉树,求法有点不同 e[n].num+=GetSum(e[n].next);*/ intp=e[n].left; e[n].num=1; while(p! =NIL) { e[n].num+=GetSum(p); p=e[p].next; } returne[n].num; } boolcmp(inta,intb) { returne[a].num>e[b].num; } voidMake(intn,boolflag) { if(n==NIL) return; intp=e[n].left; while(p! =NIL) { Make(p,flag); p=e[p].next; } e[n].visit=flag; } boolSame(inta,intb) { if(e[a].num! =e[b].num) returnfalse; if(a==NIL&&b==NIL) returntrue; if(a==NIL||b==NIL) returnfalse; intsa,sb; sa=e[a].left; while(sa! =NIL) { sb=e[b].left; while(sb! =NIL) { if(! e[sb].visit&&Same(sa,sb)) { e[sb].visit=true; break; } elseif(! e[sb].visit)//这个说明了有调用Same(sa,sb)但是他们底下有的子树相等,有的不等,所以访问标记要重设 { Make(sb,false); } sb=e[sb].next; } if(sb==NIL) returnfalse; sa=e[sa].next; } returntrue; } voidsolve() { now=-1; len=strlen(s); idx=0; ra=++now; //e[ra].left=e[rb].next=NIL; //e[ra].visit=false; build(e[ra].left,s); GetSum(ra); //len=strlen(t); idx=0; rb=++now; //e[rb].left=e[rb].next=NIL; //e[rb].visit=false; build(e[rb].left,t); GetSum(rb); if(Same(ra,rb)) { printf("same\n"); } else { printf("different\n"); } } intmain() { intT; scanf("%d",&T); while(T--) { input(); solve(); } return0; } 图的最小奇环检测(hdu1689) SampleInput 2 56 12 24 13 35 43 45 21 12 SampleOutput Case1: JYYhastouse3balls. Case2: PoorJYY. 算法就是: 从每一个顶点开始做N次bfs,在bfs过程中根据是否访问过来判断是否是否有构成环,在生成的bfs树中,每个顶点都有一个深度,用来判断生成环的长度。 加上一些剪枝: 1.已经找到长度为3的长度最小的环了。 2.2*dep+1>=ans;这个就不要再bfs下去了。 时间复杂度: O(n*n) #include #include usingnamespacestd; constintmaxn=1010; vector intn,m; intQ[maxn],f,r; intd[maxn]; boolvisit[maxn]; voidMyClear() { inti; for(i=0;i<=n;++i) { G[i].clear(); } } voidinput() { scanf("%d%d",&n,&m); inti,a,b; MyClear(); for(i=1;i<=m;++i) { scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); } } voidBFS() { intans,v,tf,tr,w; inti,dep,j; ans=INT_MAX; for(i=1;i<=n&&ans! =3;++i) { memset(visit,false,(n+1)*sizeof(bool)); f=r=0; Q[r++]=i; dep=0; d[i]=dep; while(f { if(2*dep+1>=ans) { break; } dep++; tf=f; tr=r; while(tf { v=Q[tf++]; for(j=0;j { w=G[v][j]; if(visit[w]) { if((((dep+d[w])&1)==1)&&(dep+d[w]) { ans=dep+d[w]; } } else { visit[w]=true; Q[r++]=w; d[w]=dep; } } } f=tr; } } if(ans! =INT_MAX) { printf("JYYhastouse%dballs.\n",ans); } else { printf("PoorJYY.\n"); } } intmain() { intT,cas=1; scanf("%d",&T); while(T--) { input(); printf("Case%d: ",cas++); BFS(); } return0; } 分组,组内都认识1112--TeamThemUp! TeamThemUp! TimeLimit: 1000MSMemoryLimit: 10000K TotalSubmissions: 1502Accepted: 376SpecialJudge Description Yourtaskistodivideanumberofpersonsintotwoteams,insuchaway,that: everyonebelongstooneoftheteams; everyteamhasatleastonemember; everypersonintheteamknowseveryotherpersoninhisteam; teamsareascloseintheirsizesaspossible. Thistaskmayhavemanysolutions.Youaretofindandoutputanysolution,ortoreportthatthesolutiondoesnotexist. Input Forsimplicity,allpersonsareassignedauniqueintegeridentifierfrom1toN. ThefirstlineintheinputfilecontainsasingleintegernumberN(2<=N<=100)-thetotalnumberofpersonstodivideintoteams,followedbyNlines-onelineperpersoninascendingorderoftheiridentifiers.EachlinecontainsthelistofdistinctnumbersAij(1<=Aij<=N,Aij! =i)separatedbyspaces.Thelistrepresentsidentifiersofpersonsthatithpersonknows.Thelististerminatedby0. Output Ifthesolutiontotheproblemdoesnotexist,thenwriteasinglemessage"Nosolution"(withoutquotes)totheoutputfile.Otherwisewriteasolutionontwolines.Onthefirstlineoftheoutputfilewritethenumberofpersonsinthefirstteam,followedbytheidentifiersofpersonsinthefirstteam,placingonespacebeforeeachidentifier.Onthesecondlinedescribethesecondteaminthesameway.Youmaywriteteamsandidentifiersofpersonsinateaminanyorder. SampleInput 5 2350 14530 1250 1230 43210 SampleOutput 3135 224 1、把所有的人分成2组,每组至少有1人; 2、每组之间的人两两认识。 非常明显,如果存在两个人A和B,A不认识B,或B不认识A,那么A和B一定不能分在同一组。 因此,我们以人为结点重新构造一个图G。 假如A和B不能分在同一组,那么就在G中增加一条无向边(A,B)。 这样,我们就得到了一个较为“单纯”的模型。 下面我们对这个模型进行简单分析。 我们先研究G的一个连通分量K1。 对于这个连通分量,可以先求出K1的生成树T1。 对于K1中的任意结点a,假如a在T1中的深度为奇数,我们就把a加入点集S1;否则我们把a加入点集S2(S1,S2最初为空集)。 显然最后S1,S2的交集为空。 不难证明,如果存在不同结点p和q,p和q同属于S1或S2,而且G中存在边(p,q),那么要做到满足题目要求的分组是不可能的,应输出Nosolution。 否则,我们就得到了连通分量K1的唯一分组方案: 分为S1,S2两组。 对于G中的每个连通分量Ki,我们可以求出相应的S 如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。 copyright@ 2008-2022 冰点文档网站版权所有 经营许可证编号:鄂ICP备2022015515号-1