acm代码库可复制一半版_第1页
acm代码库可复制一半版_第2页
acm代码库可复制一半版_第3页
acm代码库可复制一半版_第4页
acm代码库可复制一半版_第5页
免费预览已结束,剩余87页可下载查看

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Graph图 |无向图找 ||最大团问题DP+ ||路径 ||DIJKSTRA数组实现 |DIJKSTRAO(E*LOG |BELLMANFORD单源最短路 |SPFA(SHORTESTPATHFASTER |第K短路 K| K||PRIM求 |次小生成树 |最小生成森林问题(K颗树 |MINIMALSTEINER |TARJAN强连通分 |弦图判 ||弦图的 IMINATION点排 ||稳 问题 |拓扑排

|最小费用流O(V^2* |最佳边割 |最佳点割 |最小边割 | |最小路径覆盖 Structure数据结 |左偏树合并复杂度O(LOG |树状数 |TRIE树(K叉 |TRIE树(左儿子又兄弟 |后缀数组O(N*LOG |后缀数组 |RMQ离线算法 |RMQ(RANGE UMQUERY)-ST(O(NLOGN+ |RMQ离线算法O(N*LOGN)+O(1)求解 |LCA离线算法 |快速排 |2台机器工作调 |最长公共递增子序列 |0-1分数规 9 2-SAT问 Network网络 |二分图匹配(匈牙利算法DFS实现 |二分图匹配(匈牙利算法BFS实现 ||二分图最佳匹配(KUHNMUNKRASO(M*M*N))||无向图最小割 |DINIC最大流O(V^2* |HLPP最大流 最小费用流O(V*E*

|棋盘分 |汉诺 |STL中的 |堆 |K |二分查 Number数 1 函数 函数 |快 |扩 |模线性方程A*X=B(% |模线性方程 |筛素数 |高效求小范围素数 |组合数学相 |POLYA计 |组合数C(N, |最大1矩 |取石 |集合划分问 |线性方程组 |阶乘最后非零位,复杂度 |类循环排 |全排 |不重复排 |全组 ||不重复组 应 |字符串 |KMP匹配算法 ||| |函数名: |BM算法的改进的算法SUNDAY

Geometry计算几 |GRAHAM求凸包O(N* ||平面最近点对O(N* |判断点P是 段L | | |判断点Q是否在多边形 |解二次方程 |计算直线的一般式 | | 求点P1关于直线LN的对称点 ACM/ICPC竞赛之 ACM/ICPC竞赛之STL简 ACM/ICPC竞赛之STL-- ACM/ICPC竞赛之STL-- ACM/ICPC竞赛之STL--ITERATOR简 ACM/ICPC竞赛之STL-- ACM/ICPC竞赛之STL-- ACM/ICPC竞赛之STL-- ACM/ICPC竞赛之STL-- STLIN 头文 22Graph图

|最大团问题DP|INITg[][]邻接矩阵|CALL:res=intg[V][V],dp[V],stk[V][V],mx;intdfs(intn,intns,intdep){if(0==ns)/*==================================================*\if(dep>mx)mx=|DAG的深度优先搜索标记return|INITedge[][]邻接矩阵prepost[]tag全置|CALLdfstag(in);pre/post:开始/结束时间intijkp\*==================================================*/for(i=0;i<ns;i++)intedge[V][V],pre[V],post[V],tag;k=stk[dep][i];cnt=0;voiddfstag(intcur,intn)if(dep+n-k<=mx)return0;{//vertex:0~n-1if(dep+dp[k]<=mx)return0;pre[cur]=++tag;for(j=i+1;j<ns;j++)for(inti=0;i<n;++i)if(edge[cur][i]){p=if(0==pre[i]){if(g[k][p])stk[dep+1][cnt++]=p;printf("TreeEdge!\n");}dfstag(i,n);d,cnt,dep+}elseif(0==post[i])printf("BackEdge!\n");return1;elseif(pre[i]>pre[cur])}printf("DownEdge!\n");intn){elseprintf("CrossEdge!\n");inti,j,}for(mx=0,i=n-1;i>=0;i--)}//vertex:0~n-post[cur]=++tag;for(ns=0,j=i+1;j<n;}if(g[i][j])stk[1][ns++]= ,ns,1);dp[i]=|无向图找桥|INIT:edge[][]邻接矩阵;vis[],pre[],anc[],bridge置0;return|CALL:dfs(0,-1,1,intbridge,edge[V][V],anc[V],pre[V],vis[V];|路径voiddfs(intcurintfatherintdepintn)|INITadj[][]置为图的邻接表cnt[a]为a点的邻接点个数vertex0~n-1|CALLelpath(0);注意:不要有自向if(bridge)vis[cur]=1;pre[cur]=anc[cur]=dep;intadj[V][V],idx[V]V],cnt[V],stk[V],top;for(inti=0;i<n;++i)if(edge[cur][i]){intpath(intv){if(i!=father&&1==vis[i]){for(intw;cnt[v]>0;v={if(pre[i]<anc[cur])stk[top++]=anc[cur]=pre[i];//backedgew= t[v]}adj[w][idx[w][v]]= t[w]if0vis[itreeedge处理的是无向图—-边是双向的,删除v->w后,还要处理删除w-dfs(i,cur,dep+1,if(bridge)return;returnif(anc[i]<anc[cur])anc[cur]=if(anc[i]>pre[cur]){bridge=1;return;}voidelpath(intb,intn){//beginfrom}inti,}for(i=0;i<n;++i)//vertex:0~n-1vis[cur]=2;for(j=0;j<cnt[i];++j)}idx[i][adj[i][j]]= |无向图连通度(割)fortop0path(bb&&top0|INITedge[][]邻接矩阵;vis[],pre[],anc[],deg[]置为0;bstktop|CALL:dfs(0,-1,1,n);printf("-%d",|k=deg[0],deg[i]+1(i=1…n-1)为删除该节点后得到的连通图个数|注意:0intedge[V][V],anc[V],pre[V],vis[V],voiddfs(intcurintfatherintdepintn)|Dijkstra数组实现vertex0~n-1|Dijkstra数组实现(在此基础上可直接改为STL的Queue实现intcnt0;|lowcostbeg到其他点的最近距vis[cur1pre[curanc[curdep;|path[beg为根展开的树,记录父亲结for(inti=0;i<n;++i)if(edge[cur][i])if(i!=father&&1==vis[i]){#defineINF0x03F3F3F3Fif(pre[i]<anc[cur])constintN;anc[cur]=pre[i];//backedgeintpath[N],}voidDijkstra(intcost[][N],intlowcost[N],intn,intbeg){if(0==vis[i]){//treeedgeinti,j,min;dfs(icurdep+1n);memset(vis0sizeof(vis));t;//分支个数vis[beg]=1;if(anc[i]<anc[cur])anc[cur]=anc[i];for(i=0;i<n;if((cur==0&&cnt>1)||lowcost[i]=cost[beg][i];path[i]=beg;(cnt!=0&&anc[i]>=pre[cur]))}++deg[cur];//linkdegreeofavertexlowcost[beg]=}path[beg1树根的标}intpre=vis[cur]=2;for(i=1;i<n;}min=33for(j=0;j<n;//下面的加法可能导致溢出,INFif(vis[j]==0&&lowcost[j]=lowcost[pre]+cost[pre][j];path[j]=pre;}for(j=0;j<n;if(vis[j]==0&&lowcost[j]<min){min=lowcost[j];pre=j;}vis[pre]=}}|DijkstraO(E*log|INIT:调用init(nv,ne)读入边并初始化|CALLdijkstra(nsrc)dist[i]为src到i的最短距#definetypecint//typeofconsttypecinf=0x3f3f3f3f;//maxofcosttypeccost[E],dist[V];inte,pnt[E],nxt[E],head[V],prev[V],vis[V];structqnode{intv;typecqnode(intvv=0,typeccc=0):v(vv),c(cc)booloperator<(constqnode&r)const{returnc>r.c;voiddijkstra(intn,constintsrc){qnodemv;inti,j,k,pre;priority_queue<qnode>que;vis[src]=1;dist[src]=0;que.push(qnode(src,for(pre=src,i=1;i<n;i++)for(j=here];j!=-1;j={k=if(vis[k]==0&&dist[pre]+cost[j]<dist[k]){dist[k]=dist[pre]+cost[j];que.push(qnode(pnt[j],dist[k]));prev[k]=pre;}}while(!que.empty()&&vis[que.top().v]==1)if(que.empty())break;mv=que.top();que.pop();vis[pre=mv.v]=1;}}inlinevoidaddedge(intu,intv,typecpnt[e]=v;cost[e]=c;nxt[e]=head[u];head[u]=}voidinit(intnv,intne){inti,u,v;typecc;e=0;memset(head,-1,memset(vis,0,memset(prev,-1,for(i=0;i<nv;i++)dist[i]=inf;for(i=0;i<ne;++i){scanf("%d%d%d&u&v&cdtypeofcostaddedge(u,v,c);//vertex:0~n-1,单向边}}|BellmanFord单源最短路 能在一般情况下,包括存在负权边的情况下,解决单源最短路径问|INITedge[E][3]为边|CALL:bellman(src);有负环返回0;dist[i]为src到i的最短|可以解决差分约束系统:需要首先构造约束图,构造不等式时>=表示求最小值为最长路,<=表示求最大值作为最短路(v-uc:a[u][v#definetypecint//typeofconsttypecinf=0x3f3f3f3f;//maxofcostintn,m,pre[V],edge[E][3];typecintrelax(intu,intv,c){if(dist[v]>dist[u]+{dist[v]=dist[u]+

pre[v]=u;return}return}intbellman(intsrc){inti,j;for(i=0;i<n;++i)dist[i]=inf;pre[i]=-}dist[src]=0;boolflag;for(i=1;i<n;++i){flagfalse优for(j=0;j<m;++j)if(1==relax(edge[j][0],edge[j][1],edge[j][2]))flag=true;}if(!flag)break;}for(j=0;j<m;++j){if1relax(edge[j][0edge[j][1]edge[j][2]))return0;//有负圈}return}|SPFA(ShortestPathFasterBellman-Ford算法的一种队列实现,减少了不必要的冗余计算。它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负边。原理:只有那些一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的改变。判断负权回路:记录每个结点进队次数,超过|V|次表示有//POJ3159constintINF=0x3F3F3F3F;constintV=30001;constintE=intpnt[E],cost[E],inte,head[V];intdist[V];boolvis[V];intmain(void){intn,while(scanf("%d%d",&n,&m)!=EOF){inti,a,b,c;e=memset(head,-1,sizeof(head));for(i=0;i<m;++i)b-ac有向边(ab):c,边的方向!!!scanf("%d%d%d",&a,&b,&c);addedge(a,b,c);}printf("%d\n",SPFA(1,}return}intrelax(intu,intv,c){if(dist[v]>dist[u]+c{dist[v]=dist[u]+c;return}return}inlinevoidaddedge(intu,intv,intpnt[e]=v;cost[e]=c;nxt[e]=head[u];head[u]=}intSPFA(intsrc,int{//此处用堆栈实现,有些时候比intfori=1ini顶点vis[i]=0;dist[i]=}dist[src]=intQ[E],top=Q[0]=src;vis[src]=true;while(top){intu,u=Q[--top];vis[u]=for(i=head[u];i!=-i=nxt[i]){v=if(1==relax(u,v,cost[i])&&!vis[v]{Q[top++]=v;vis[v]=}}}return}4队列实现,而且有负权回路判断POJ3169Layout#defineswap(t,a,b)(t=a,a=b,b=t)constintINF=0x3F3F3F3F;constintV=1001;constintE=intpnt[E],cost[E],inte,head[V],dist[V];boolvis[V];intcnt[V入队列main(void){intn,ml,md;while(scanf("%d%d%d",&n,&ml,&md)!=EOF){inti,a,b,c,t;e=memset(head,-1,fori=0imli大-小<=c向边(小scanf("%d%d%d",&a,&b,if(a>b)swap(t,a,addedge(a,b,}for(i=0;i<md;++i大-小>=c小-大<=-c向边scanf("%d%d%d",&a,&b,if(a<b)swap(t,a,addedge(a,b,-}//for(i=1;i<=n;++i)printf("%d\n",dist[i]);printf("%d\n",SPFA(1,n));}return}intrelax(intu,intv,c){if(dist[v]>dist[u]+c{dist[v]=dist[u]+c;return}return}inlinevoidaddedge(intu,intv,intpnt[e]=v;cost[e]=c;nxt[e]=head[u];head[u]=}intSPFA(intsrcintn){此处用队列实intmemset(vis,false,for(i=1;i<=n;++i)dist[i]=INF;dist[src]=0;queue<int>Q.push(src);vis[src]=true; while(!Q.empty()){intu,u=Q.front();Q.pop();vis[u]=false;for(i=head[u];i!=-1;i=nxt[i]){v=if(1==relax(u,v,cost[i])&&!vis[v]{Q.push(v);vis[v]=if( t[v])>n)return-1;//为入队列次数,用来判断是否存}}}if(dist[n]==INF)return-2;// 的最短距离,根据题意不同而改}|第K短路 dij变形,可以证明每个点经过的次数为小于等于K,所有把dij的数组 由一维变成2维,记录经过该点1次,2次。。。k次的最小值|输出dist[n-1][kintintintv[1010];intmain(){(scanf("%d%d%d",&n,&m,&x)!=EOF){for(inti=1;i<=n;i++)

fori=0;i<m;i++){intif(r<g[p][q])}fori=1;i<=n;i++){for(intj=0;j<=x;j++)}whileintfor(intif(v[i]<x&&dist[i][v[i]]<dist[k][0])if(k==0)if(k==n&&v[n]==x-1)break;for(inti=1;i<=n;i++){if(v[i]<x&&for(intj=x;j>0;j--)if(dist[i][j]<dist[i][j-swap(dist[i][j],dist[i][j-}}if(dist[n][x-1]<INF)printf("%d\n",dist[n][x-1]);elseprintf("-1\n");}return}|第K短路|A*估价函数fi为到当前点走过的路经长度,hi为该点到终点的长|intintintdist[1010],v[1010];structnode{intfriendbooloperator<(nodea,nodeb){if(a.gi==b.gi)returna.fi>b.fi;returna.gi>b.gi;}intfori=0;i<=n;i++){dist[i]=INF;v[i]=1;}for(inti=0;i<n;i++){intfor(intif(v[j]&&dist[j]<dist[k])k=j;if(k==n)break;for(intif(v[j]&&}return}intif(dist[0]==INF)return-1;intcnt=0;whileif(id==n-1)cnt++;if(cnt==x)returnfi;5ct--for(intj=0;j<n;j++)if}

|最小生成森林问题(k树数据结构:并查集算法:改进根据Kruskal算法思想,图中的生成树在连完第n-1条边前,都是一个最小生成森林,每次贪心的选择两个不属于同一连通分量的树(如果连接通分量,因为不会减少块数,那么就是不合算的)且用最“便宜”的边连起来,连接n-1次后就形成了一棵MST,n-2次就形成了一个两棵树的最小生成森林n-3,……,n-k此后就形成了k颗树的最小生成森林,就是题目要求求解的。 -|有向图最小树形图|INITeg置为边表res置为0cp[i]置为i;int|CALLdirtree(rootnvne)res是结果;while\*==================================================*/for(int#definetypecint//typeofresfor(intconsttypecinf=0x3f3f3f3f;//maxofresgr[i][j]=g[i][j]=INF;typecres,dis[V];for(inti=0;i<m;i++){intto[V],cp[V],tag[V];intstructEdge{intu,v;typecc;}eg[E];scanf("%d%d%d",&x,&y,&z);intiroot(inti){x--,y--;g[x][y]<?=z;if(cp[i]==i)returngr[y][x]<?=z;returncp[i]=init();intdirtree(introotintnvintnerootprintf("%d\n",solve());{//vertex:0~n-}inti,j,k,circle=return0;memset(tag,-1,}memset(to,-1,/*==================================================*\for(i=0;i<nv;++i)dis[i]=|Prim求MSTfor(j0jnej|INITcost[][]耗费矩阵(inf为无穷大);iiroot(eg[j].ukiroot|CALLprim(costn返回-1代表原图不连通;ifki&&dis[keg[j].c\*==================================================*/dis[k]=#definetypecint//typeofcostto[k]=i;consttypecinf=0x3f3f3f3f;//maxofcost}intvis[V];typeclowc[V];}typecprim(typeccost[][V],intn)//vertex:0~n-1to[root]=-1;dis[root]=0;tag[root]={for(i=0;i<nv;++i)if(cp[i]==i&&-1==tag[i]){inti,j,p;j=i;typecminc,res=0;for(;j!=-1&&tag[j]==-1;j=to[j])memset(vis,0,sizeof(vis));tag[j]=i;vis[0]=1;if(j==-1)returnfor(i=1;i<n;i++)lowc[i]=cost[0][i];if(tag[j]=={for(i=1;i<n;i++){circle=1;tag[j]=-minc=inf;p=-1;for(k=to[j];k!=j;k=to[k])tag[k]=-2;for(j=0;j<n;j++)}if(0==vis[j]&&minc>lowc[j]){}minc=lowc[j];p=j;if(circle){}for(j=0;j<ne;++j)ifinfmincreturn1;原图不连通iiroot(eg[j].ukiroot(eg[j].v);res+=minc;vis[p]=1;if(k!=i&&tag[k]==-2)eg[j].c-=dis[k];for(j=0;j<n;if(0==vis[j]&&lowc[j]>cost[p][j])for(i=0;i<nv;++i)if(tag[i]==-{lowc[j]=cost[p][j];res+=dis[i];tag[i]=}for(j=to[i];j!=i;j=to[j])returnres;res+=dis[j];cp[j]=i;tag[j]=|次小生成树O(V^2)if0dirtree(rootnvne)return\*==================================================*/}else结论次小生成树可由最小生成树换一条边得到.fori0inviifcpiires证明:可以证明下面一个强T是某一棵最小生成树,T0是任一棵异于T的树,通过变换T0-->T1-->return1;//若返回0代表原图不连T2TnT变成最小生成树.所谓的变换是,每次把T_i中的/*==================================================*\某条边换成T中的一条边 而且树T_(i+1)的于T_i的权

|MinimalSteinerTree具体操作是|G(V,E),A是V的一个子集,求至少包含A中所有点的最小子树.step1.在T_i中任取一条不在T中的边step2把边u_v去掉,就剩下两个连通分量A和B,在T中,必有唯|时间复杂度:O(N^3N*2^A*2^A|INITd[][]距离矩阵id[]置为集合A中点的标号;边u'_v结A和step3显然u'_v'的权比u_v(否则,u_v就应该在T中).把u'_v|CALLsteiner(intnint|main()函数解决的题目TickettoRideNWERC2006/2007替换u_v即得树特别地:取Tn为任一棵次小生成树,T_(n-1就是次小生成树且跟T|给4个点对(a1b1(a4|求min(sigma(dist[ai][bi])),其中重复的路段只能算一次.差一条边.结论得证|这题要找出一个steiner森林后要对森林中树的个数进行枚举step1.先用prim求出最小生成树T.在prim的同时,用一个矩阵#definetypecint//typeofcostmax[u][v记录在T中连结任意两点u,v的唯一的路中权值最大的那条边的consttypecinf0x3f3f3f3fmaxof权值(注意这里这是很容易做到的,因为prim是每次增加一个结点sintvis[Vid[A];//idA中点的标设已经标号了的结点集合为W,则W中所有的结点到s的路中的最大权值的边就typecd[V][V],dp[1<<A][V];//dp[i][v]:点v到点集i的最短距voidsteiner(intninta){是当前加入的这条边.step1用时intijkmxmktop1a);step2枚举所有不在T中的边u_v,加入边u_v替换权为fork0knkfori0ini++)不断更新求最小值,即次小生成树.step2用故总时间为66for(j=0;j<n;if(d[i][j]>d[i][k]+d[i][j]=d[i][k]+d[k][j];for(i=0;i<a;i++){//vertex:0~n-1for(j=0;j<n;dp[1<<i][j]=d[j][id[i]}for(i=1;i<top;i++)if(0==(i&(i-1)))continue;memset(vis,0,sizeof(vis));for(k=0;k<n;k++){//for(dp[i][k]=inf,j=1;j<i;j++)if((i|j)==i&&

intg[V][V],order[V],inv[V],tag[V];voidmcs(intn){inti,j,memset(tag,0,memset(order,-1,for(i=n-1;i>=0;i--){//vertex:0~n-1for(j=0;order[j]>=0;j++);for(k=j+1;k<n;if(order[k]<0&&tag[k]>tag[j])j=k;order[j]=i,inv[i]=j;for(k=0;k<n;k++)if(g[j][k])}}dp[i][k]=dp[j][k]+dp[i-j][k];inti,j,k,w, for(i=n-2;i>=0;i--)for(j=0;mx=inf,j<n;j++){//updatefor(k=0;k<n;k++)if(dp[i][k]<=mx&&0==vis[k])mx=dp[i][mk=k];for(k=0,vis[mk]=1;k<n;if(dp[i][mk]>dp[i][k]+dp[i][mk]=dp[i][k]+}}

j=inv[i],w=-1,min=n;for(k=0;k<n;k++)if(g[j][k]&&order[k]>order[j]&&order[k]<min)min=order[k],w=k;if(w<0)continue;for(k=0;k<n;if(g[j][k]&&order[k]>order[w]&&!g[k][w])return0;//nointmain(void){return1;//yesintn,a=8;}//TODO:readsteiner(n,a);|弦图的 imination点排enumtofindtheresult|INITg[][]置为邻接矩阵fori0binfz0i256b>zb=zbi|CALLcardinality(ntag[i]为排列中第i个点的标号;for(j=0;y=0,j<4;z+=!!y*dp[y][x],j++)|Thegraphwiththepropertymentionedabovefor(k=0;k<8;k+=2)|iscalledchordalgraph.rmutations=[v1,if((i>>k&3)==j)|...,vn]oftheverticesofsuchgraphiscalledy+=3<<k,x=id[k];| iminationorderifeachviisa//TODO:cout<<b<<endl;|vertexofthesubgraphofGinducedby{vi,...,vn}.return0;|Avertexiscalledsimplicialifitsadjacencyset}|inducesacompletesubgraph,thatis,aclique/*==================================================*\| al).The imination|Tarjan强连通分量|ofachordalgraphcanbecomputedasthe|INITvec[]为邻接表stopcntscnt置0pre[]置-|CALL:for(i=0;i<n;++i)if(-1==pre[i])tarjan(i,n);procedureumcardinalitysearch(G,forallverticesvofGdo\*==================================================*/setlabel[v]tozerovector<int>vec[V];endforintid[V],pre[V],low[V],s[V],stop,cnt,forallifromndownto1dovoidtarjan(intv,intn)//vertex:0~n-1chooseanunnumberedvertexvwithlargestlabel{sets(vtoi{numbervertexv}intt,minc=low[v]=pre[v]=forallunnumberedverticeswadjacenttovertexvdovector<int>::iteratorpvincrementlabel[w]byones[stop++]=v;endforfor(pv=vec[v].begin();pv!=vec[v].end();{endforif(-1==pre[*pv])tarjan(*pv,n);endprocedureif(low[*pv]<minc)}inttag[V],g[V][V],deg[V],vis[V];if(minc<{voidcardinality(intn)low[v]=minc;|弦图判断|INITg[][]置为邻接矩阵;vis[k1tag[i|CALL:mcs(n);peo(n);for(j=0;j<n;

inti,j,k;domemset(deg,0,sizeof(deg));id[t=s[--stop]]=scnt;low[t]=memset(vis,0,sizeof(vis));}while(t!=forin1i0i t;//强连通分量的个for(j=0,k=-1;j<n;j++)if(0==vis[j]){}if(k==-1||deg[j]>deg[k])k=|第一步:给节点mcs(n)if(0==vis[j]&&g[k][j])|设已的节点集合为 未的节点集合为|开始时A为空,B包含所有节点|fornum=n-1downto0do|在B中找节点x,使与x相邻的在A集合中的节点数最多,|稳定问题|将x为num,并从B移入constintN=structPeople{|第二步:检查peo(n)boolstate;|fornum=0ton-1dointopp,tag;|对为num的点x,设所有>num且与x相邻的点集为intlist[N];//man使用|在C中找出最小的节点intpriority[N];//woman使用,有必要的话可以和list合并,|若C中存在点z!=y,使得y与z之间

以节省空间voidInit(statetag0|检查完了,则此图是弦图77structintopp;intintn;voidInput(void);intmain(void){}Input(void){%d\n",&n);inti,j,for(i=0;i<n;++i{forj=0jnj按照man的意愿递减排序scanf("%d&ch)man[i].list[jch-}}for(i=0;i<n;++i{forj=0jnj按照woman的意愿递减排序,scanf("%d",&ch);woman[i].priority[ch-1]=}

for(i=0;i<n;++iiftop1printf("存在回路\n")returnintj=top;top=count[top];printf("%d",j);for(intk=0;k<n;++kif(edge[j][k]&&(--count[k])0){count[k]=top;top=}}}|无向图连通分支(dfs/bfs邻接阵|DFSBFS并查|有向图强连通分支(dfs/bfs邻接//返回分支数,id返回1..分支#defineMAXN100voidsearch(intn,intmat[][MAXN],int*dfn,int*low,intnow,int&cnt,int&tag,int*id,int*st,int&sp){inti,j; for(i=0;i<n;i++)ifif}}stableMatching(void){intk;for(k=0;k<+k){inti,id=0;for(i=0;i<n;++i)if(man[i].state0){requst[id].opp=man[i].list[man[i].tag];requst[id].own=man[i].tag+=1;}if(id==0)break;for(i=0;i<id;++i){if(woman[requst[i].opp].state0){woman[requst[i].opp].opp

if(low[i]<low[now])}elseifif(j<cnt&&dfn[i]<low[now])}}iffor(tag++;st[sp]!=now;id[st[--}

woman[requst[i].opp].state=

t,sp,st[MAXN],dfn[MAXN],low[MAXN];forfor( if(!dfn[i]) return}//有向图强连通分支,bfs邻接阵形式//返回分支数,id返回1..分支数的#defineMAXN100if(woman[requst[i].opp].priority[woman[requst[i].oint ponents(intn,intmat[][MAXN],int*id){pp].opp]>intret=0,a[MAXN],b[MAXN],c[MAXN],d[MAXN],i,j,k,t;woman[requst[i].opp].priority[requst[i].own]){//for(k=0;k<n;id[k++]=0);forman[woman[requst[i].opp].opp].state=0;if(!id[k]){woman[requst[i].opp].opp=for(i=0;i<n;i++)man[requst[i].own].state=1;a[k]=b[k]=1;man[requst[i].own].opp=for(t=1;t;)requst[i].opp;for}if}for}if}ifvoidOutput(void){forfor(inti=0;i<n;++i)printf("%d\n",man[i].opp+1);if|拓扑排序for|INIT:edge[][]置为图的邻接矩阵;count[0…i…n-1]:顶点i的入度.ifvoidTopoOrder(intinti,top=-1;returnret;for(i=0;i<n;++i)}ifcount[i0下标模拟堆栈count[i]=top;top=8|有向图最小点基(邻接阵 点基B满足:对于任意一个顶点Vj,一定存在B中的一个Vi,使得Vi是|的前代//返回点基大小和点//传入图的大小n和邻接阵mat,不相邻点边权#defineMAXN100intbase_vertex(intn,intmat[][MAXN],int*sets){intret=0,id[MAXN],v[MAXN],i,j;for(i=0;i<j;v[i++]=1);for(i=0;i<n;i++)iffor(i=0;i<n;i++)if(v[id[i]-returnret;}|Floyd求最令e(u,v)表示u和v之间的连边min(u,v)表示删除u和v之间的连边之后u和v之间的最短路最小环则是min(uve(uv时间复杂度是g[i][j]=i,j之间的边长fork:=1tondofori:=1tok-1doforj:=i+1tok-1doanswer:=min(answer,dist[i][j]+g[i][k]+g[k][j]);fori:=1tondoforj:=1ton最小环改进算法的证代表了i到j的路径中所有结点都小于k的最短路径constintINF=1000000000;constintN=110;intnmn:节点个数m:边的个数intg[N][N];//无向图intdist[N][N]最短路intr[N][Nr[i][ji到j的最短路径的第一步intout[N],ct;//记录最小环intsolve(intiintjintk记录最小ct= i){ }out[ct++]=i;out[ct++]=k;return0;}intwhile(scanf("%d%d",&n,&m)!=EOF){inti,j,k;for(i=0;i<n;i++for(j=0;j<n;j++){=INF;r[i][j]=}for(i=0;i<i++){intx,y,l;scanf("%d%d%d",&x,&y,&l);--x;--if(l<g[x][y])g[x][y]=g[y][x]=}intMin=INF;//最小环for(k=0;k<n;k++fori=0iki一个环中的最大结点为k(

if(g[k][i]<INFfor(j=i+1;j<k;j++if(dist[i][j]<INF&&<INF&&Min>dist[i][j]+g[k][i]+g[k][j]Minsolve(ijk)记录最}for(i=0;i<n;i++if(dist[i][k]<INFfor(j=0;j<n;j++if(dist[k][j]<INF&&dist[i][j]>dist[i][k]+dist[k][j]){dist[i][j]r[i][j]=}}if(Min<INFfor(ct--;ct>=0;ct--printf("%d",if(ct)printf("}}}return}|2-sat问 N ,每个2个人,现在要想选出尽量多的人且每 只能选出一个人。如果两人有,他们不能同时被选问最多能选出多少constintMAXN=3010;intn,m;intx[3010],y[3010];intprev[MAXN],low[MAXN],stk[MAXN],sc[MAXN];intcnt[MAXN];intcnt0,ptr,voidw){intmin(0);prev[w]=cnt0++;low[w]=prev[w];min=low[w];stk[ptr++]=w;for(inti=0;i<++i){intt=if(prev[t]==-1)if(low[t]<min)min=} low[w]){low[w]=min;}intv=stk[--ptr];sc[v]=cnt1;low[v]=}while(stk[ptr]!=w);}voidTarjan(int强连通分量数为cnt0=cnt1=ptr=0;inti;for(i=0;i<N;++i)prev[i]=low[i]=-1;for(i=0;i<N;++i)if(prev[i]==-}solve(){Tarjan(n);for(inti=0;i<n;i++){99if(sc[i]==sc[f[i]])return}return}intcheck(intfor(inti=0;i<n;i++)fori=0;i<Mid;i++){}return}intwhile(scanf("%d%d",&n,&m)!=EOF&&n+m){for(inti=0;i<n;i++){intp,q;}for(inti=0;i<m;i++)scanf("%d%d",&x[i],&y[i]);whileintelseMax=Mid;}}return}Network网络

}}if(Mx[i]!=-1)}}return|二分图匹配(匈牙利算法DFS实现|INITg[][]邻接矩阵;|二分图匹配(Hopcroft-Carp的算法|CALLresMaxMatch();|INITg[][]邻接矩阵|优点:实现简洁容易理解,适用于稠密图,DFS找增广路快。|CALL:res=MaxMatch();Nx,Ny要初始|找一条增广路的复杂度为O(E)最多找V条增广路,,故时间复杂度为O(VE)|时间复杂度为O(V^0.5constintMAXN=1000;constintMAXN=intuNvNuv数目,要初始化!!!constintINF1boolg[MAXN][MAXNg[i][j表示xi与yj相连intg[MAXN][MAXNMx[MAXN]My[MAXNNxNy;intxM[MAXN],yM[MAXN];//输出量intdx[MAXN],dy[MAXN],dis;boolchk[MAXN]辅助量检查某轮y[v]是否被checkboolvst[MAXN];boolSearchPath(intu){boolsearchP(void){intv;queue<int>for(v=0;v<vN;v++)dis=if(g[u][v]&&!chk[v])memset(dx,-1,{memset(dy,-1,chk[v]=true;for(inti=0;i<Nx;if(yM[v]==-1||SearchPath(yM[v]))if(Mx[i]==-{Q.push(i);dx[i]=yM[v]=u;xM[u]=returntrue;while(!Q.empty())}intu=Q.front();}if(dx[u]>dis)returnfalse;for(intv=0;v<Ny;}if(g[u][v]&&dy[v]==-{intMaxMatch(){dy[v]=intu,ret=0;if(My[v]==-1)dis=dy[v];memset(xM,-1,sizeof(xM));else{memset(yM,-1,sizeof(yM));dx[My[v]]=dy[v]+1;for(u=0;u<uN;u++)Q.push(My[v]);if(xM[u]==-memset(chk,false,sizeof(chk));}if(SearchPath(u))ret++;}}returndis!=INF;returnret;}}boolDFS(int/*==================================================*\for(intv=0;v<Ny;|二分图匹配(匈牙利算法BFS实现)ifvst[v&&g[u][v&&dy[vdx[u]+1|INITg[][]邻接矩阵;vst[v|CALLresMaxMatch();NxNy初始化!!!ifMy[v1&&dy[vdis|优点:适用于稀疏二分图,边较少,增广路较短。if(My[v1||DFS(My[v])|匈牙利算法的理论复杂度是O(VE)My[vuMx[u constintMAXN=intg[MAXN][MAXN],Mx[MAXN],My[MAXN],Nx,intchk[MAXN],Q[MAXN],prev[MAXN];return0;intMaxMatch(void){}intres=0;intMaxMatch(void){intqs,qe;intres=0;memset(Mx,-1,sizeof(Mx));memset(Mx,-1,memset(My,-1,sizeof(My));memset(My,-1,sizeof(My));memset(chk,-1,sizeof(chk));while(searchP()){for(inti=0;i<Nx;i++){memset(vst,0,sizeof(vst));if(Mx[i]==-1){for(inti=0;i<Nx;i++)qs=qe=0;if(Mx[i]==-1&&DFS(i))res++;e++]=i;}prev[i]=-1;return}boolflag=while(qs<qe&&!flag){|二分图最佳匹配(kuhnmunkras算法O(m*m*n))intu= s];|邻接距阵形式,复杂度O(m*m*n)返回最佳匹配值,传入二分图大小m,nforintv0vNy&&flagv++)|邻接距阵mat,表示权match1,match2返回一个最佳匹配,未匹配顶点if(g[u][v]&&chk[v]!=i){|match值为-1,一定注意m<=n,否则循环无法终止,最小权匹配可将权值chk[v e++My[v];|if(My[v0prev[My[vu|初始化:fori=0iMAXNielse{for(j=0;j<MAXN;++j)mat[i][j=-inf;flag1;|对于存在的边:mat[i][jval注意,不能有负intd=u,e=while(d!=-1){#include<string.h>intt=Mx[d];#defineMAXN310Mx[d]=e;My[e]=d;#defineinfd=prev[d];e=t;#define_clr(x)memset(x,-}intkuhn_munkras(intm,intn,intmat[][MAXN],int*match1,int*match2){forfor(l1[i]=-inf,j=0;j<n;j++)ifl1[iinfreturn1无法匹配}forforfor(k=s[p],j=0;j<n&&match1[i]<0;j++)iffor

|有上下界的最小|INIT:up[][]为容量上界;low[][]为容量下界|CALLmflimitflow(n,src,sinkflow[][]为流量分配|另附环流问|描述:无源无汇的网络N,设N是具有基础有向图D=(V,A)的网络|l和c分别为容量下界和容量上界 如果定义在A上的函|f满足f(vVf(VvV中任意顶点|l(a)<=f(a)<=c(a),则称f为网络N的循环流|解法:添加一个源s和汇t,对于每个下限容量l不为0的边(u,|将其下限去掉限改为c-l加两条边(ut)s|容量均为 原网络存在循环流等价于新网络最大流是满流intup[N][N],low[N][N],flow[N][N];intpv[N],que[N],d[N];voidmaxflow(intn,intsrc,intBFS增广O(E*maxflow)intp,q,t,i,j;}iffor(j=0;j<n;j++)p=l1[s[k]]+l2[j]-forfor(k=0;k<=q;l1[s[k++]]-}}for{//if处理无匹配的情况if(match[i]<0)return-if(mat[i][match[i]]<=-inf)return-1;}return}|无向图最小割|INIT:初始化邻接矩阵|CALL:res=|注Stoer-WagnerMinimum 找边的最小集合,若其被删去则图变得不连通(把这种形式称为最|割问题#definetypecint//typeofconsttypecinf=0x3f3f3f3f;//maxofresconsttypecmaxw=1000;//umedgeweighttypecg[V][V],w[V];inta[V],v[V],na[V];typecmincut(intn){inti,j,pv,typecbest=maxw*n*for(i=0;i<n;i++)v[i]=i;//vertex:0~n-1while(n>1){for(a[v[0]]=1,i=1;i<n;i++)a[v[i]]=0;na[i-1]=w[i]=}for(pv=v[0],i=1;i<n;i++{for(zj=-1,j=1;j<n;j++if(!a[v[j]]&&(zj<0||w[j]>w[zj]))zj=j;a[v[zj]]=if(i==n-1)if(best>w[zj])best=w[zj];for(i=0;i<n;i++)g[v[i]][pv]=g[pv][v[i]]}pv=for(j=1;j<n;j++)w[j]+=}}return}

for(i=0;i<n;pv[i++]=0);pv[t=src]=src+1;d[t]=inf;for(p=q=0;p<=q&&!pv[sink];t=que[p++])for(i=0;i<n;i++){elseifpv[que[q++]=i]=-t-1,}for(i=sink;pv[i]&&i!=src;)if(pv[i]>0)flow[pv[i]-1][i]+=d[sink],i=pv[i]-elseflow[i][-pv[i]-1]-=d[sink],i=-pv[i]-}}while}intlimitflow(intn,intsrc,int{inti,j,sk,if(src==sink)returnup[n][n+1]=up[n+1][n]=up[n][n]=up[n+1][n+1]=0;for(i=0;i<n;i++){up[n][i]=up[i][n]=up[n+1][i]=up[i][n+1]=0;for(j=0;j<n;j++){up[i][j]-=up[n][i]+=up[i][n+1]+=}}sk=up[src][sink];ks=up[sink][src];up[src][sink]=up[sink][src]=inf;maxflow(n+2,n,n+1);for(i=0;i<n;if(flow[n][i]<up[n][i])return-1;flow[src][sink]=flow[sink][src]=0;up[src][sink]=sk;up[sink][src]=ks;//!min:src<-sink;max:src->sink;maxflow(n,sink,src);for(i=0;i<n;i++)for(j=0;j<n;{up[i][j]+=low[i][j];flow[i][j]+=}for(j=i=0;i<n;j+=flow[src][i++]);returnj;}|Dinic最大流O(V^2*|INITne=2head[]置为0addedge()加入所有弧|CALL:flow(n,s,#definetypecint//typeofconsttypecinf=0x3f3f3f3f;//maxofcoststructedge{intx,y,nxt;typecc;}bf[E];intne,head[N],cur[N],ps[N],dep[N];voidaddedge(intx,inty,typec{//addanarc(x->y,c);vertex:0~n-1;bf[ne].x=x;bf[ne].y=y;bf[ne].c=c;bf[ne].nxt=head[x];head[x]=ne++;bf[ne].x=y;bf[ne].y=x;bf[ne].c=0;bf[ne].nxt=head[y];head[y]=ne++;}

typecflow(intn,ints,int{typectr,res=

intv,s,t,h[N],hn[2*N],cur[N];inti,j,k,f,r,top;voidpush(int);while(1){voidrelabel(int);memset(dep,-1,n*voidbuild(int,int);for(f=dep[ps[0]=s]=0,r=1;f!=r;)typefmaxflow(int,int);for(i=ps[f++],j=head[i];j;j=bf[j].nxt)if(bf[j].c&&-1==dep[k=bf[j].y]){voidnetwork::push(intu)edge*te=net[u][cur[u]];dep[k]=dep[i]+1;ps[r++]=k;typefex=minf(te->cap(u),e[u]);if(k==t){f=r;break;}intp=te->other(u);}if(e[p==0&&p!=t)list.insert(p,te->addflow(u,ex);e[u]-=ex;e[p]+=ex;if(-1==dep[t])}voidnetwork::relabel(intu){memcpy(cur,head,n*sizeof(int));inti,p,mh=2*v,oh=h[u];for(i=s,top=0;;){for(i=net[u].size()-1;i>=0;i--){if(i==t)p=net[u][i]->other(u);for(k=0,tr=inf;k<top;if(net[u][i]->cap(u)!=0&&mh>h[p]+1)if(bf[ps[k]].c<tr)mh=h[p]+1;tr=bf[ps[f=k]].c;}for(k=0;k<top;hn[h[u]--;hn[mh]++;h[u]=mh;bf[ps[k]].c-=tr,bf[ps[k]^1].c+=tr;cur[u]=net[u].size()-1;res+=tr;i=bf[ps[top=f]].x;}if(hn[oh]!=0||oh>=v+1)return;for(j=cur[i];cur[i];j=cur[i]=bf[cur[i]].nfor(i=0;i<v;i++)if(bf[j].c&&dep[i]+1==dep[bf[j].y])break;if(h[i]>oh&&h[i]<=v&&i!=s){if(cur[i])hn[h[i]]--;hn[v+1]++;h[i]=v+1;ps[top++]=}i=}|HLPPO(V^3)a<b?a:b;

typefnetwork::maxflow(intss,inttt){s=ss;t=tt;if(0==top)inti,p,u;typefec;dep[i]=-1;i=bf[ps[--for(i=0;i<v;i++)for(i=eg.size()-1;i>=0;i--){}memset(h,0,sizeof(h));memset(hn,0,sizeof(hn));|INIT:networkg;g.build(memset(e,0,sizeof(e));e[s]=inf;|CALL:res=g.maxflow(s,t);fori0ivi+h[iv;|注意:不要加入指向源点的边,可能死循环queue<int>q;q.push(t);h[t]while(!q.empty()){#definetypefint//typeofp=q.front();q.pop();consttypefinf=0x3f3f3f3f;//maxoffor(i=net[p].size()-1;i>=0;i--){typefminf(typefa,typefb){u=net[p][i]-ec=net[p][i]->cap(u);structedgeif(ec!=0&&h[u]==v&&u!=s){intu,v;typefcuv,cvu,edge(intx=0,inty=0,typefcu=0,h[u]=h[p]+1;q.push(u);typefcv=0,typeff=0)}:u(x),v(y),cuv(cu),cvu(cv),flow(f){}}intother(intp){returnp==u?v:u;}}typefcap(intp){for(i=0;i<v;i++)hn[h[i]]++;returnp==u?cuv-flow:cvu+flow;}for(i=0;i<v;i++)cur[i]=net[i].size()-voidaddflow(intp,typeff){flow+=(p==u?f:-f);};for(;cur[s]>=0;cur[s]--)structvlistintlv,next[N],idx[2*N],v;voidclear(intcv){v=cv;lv=-memset(idx,-1,}voidinsert(intn,int{next[n]=idx[h];idx[h]=n;if(lv<h)lv=h;}intremove()intr=idx[lv];idx[lv]=next[idx[lv]];while(lv>=0&&idx[lv]==-1)lv--;returnr;}boolempty(){returnlv<0;

while(!list.empty())for(u=list.remove();e[u]>0;{if(cur[u]<0)elseif(net[u][cur[u]]->cap(u)>0h[u]==h[net[u][cur[u]]-elsecur[u]--}}return}voidnetwork::build(intn,int{v=n;eg.clear();inta,b,i;typefl;for(i=0;i<m;i++){cin>>a>>b>>eg.push_back(edge(a,b,l,0));//vertex:0~n-}struct{vector<edge>eg;vlistlist;typef

|最小费用流O(V*E*|INIT:networkg;g.build(v,|CALL:g.mincost(s,t);flow=g.flow;|注意SPFA增广实际复杂度远远小于O(V*#definetypefint//typeofflow#definetypecint//typeofconsttypefinff=0x3f3f3f3f;//maxofflowconsttypecinfc=0x3f3f3f3f;//maxofdisstructnetwork{intnv,ne,pnt[E],intvis[N],que[N],head[N],pv[N],pe[N];typefflow,c];typeccost,dis[E],d[N];voidaddedge(intu,intv,typefc,typecw)pnt[ne]=v;cap[ne]=dis[ne]=+w;nxt[ne]=head[u];head[u]=(ne++);pnt[ne]=u;cap[ne]=0;dis[ne]=-w;nxt[ne]=head[v];head[v]=}intmincost(intsrc,int{inti,k,f,r;typefmxf;for(flow=0,cost=0;;{memset(pv,-for(i=0;i<nv;++i)d[i]=d[src]=0;pv[src]=src;vis[src]=for(f=0,r=1,que[0]=src;r!=f;{i=que[f++];vis[i]=0;if(N==f)f=0;for(k=head[i];k!=-1;k=if(cap[k]&&dis[k]+d[i]<{d[pnt[k]]=dis[k]+if(0==vis[pnt[k]])vis[pnt[k]]=que[r++]=pnt[k];if(N==r)r=}pt[k]]=i;}}if(-1==pv[sink])

intu,v;typefcuv,cvu,flow;typecedge(

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论