省选图论专题
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了省选图论专题相关的知识,希望对你有一定的参考价值。
省选图论专题
P1344 [USACO4.4]追查坏牛奶
输出最小割和在最小割前提下的最小割边数目。
最小割跑 d i n i c dinic dinic,最小割边转换一下:令边权 w = w × b l + 1 w=w\\times bl+1 w=w×bl+1
b l > 1000 bl>1000 bl>1000,这样跑出来的最小割答案 ( m o d b l ) \\pmod {bl} (modbl)就是边数。
因为所有的 1 1 1加起来不会大于等于 b l bl bl,所以 a n s m o d b l = c n t e d g e ans\\bmod{bl}=cnt_{edge} ansmodbl=cntedge
而 a n s b l \\dfrac{ans}{bl} blans就是真实的答案,同理 s u m 1 < b l sum_1<bl sum1<bl 不会被算入真实的答案中。
st=1,ed=n;int bl=1001;
for(int i=1,u,v,w;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
w=w*bl+1;
add(u,v,w);
}
ll ans=dinic();
printf("%lld %lld\\n",ans/bl,ans%bl);
P1606 [USACO07FEB]Lilypad Pond G
给定起点和终点,求跳马步到终点需要填加的最小结点,以及方案数。
草,是最短路!若目标节点没有莲花。
然后就是最短路和最短路计数。
本题难点在于建图,而对于有荷花的点贡献为0,0权边对于方案数处理会出现问题,因为如果0权边在环里会重复计数。
所以我们考虑建图的时候如果下一个结点是莲化,就一直找到第一个水点建立1权边,终点也建立1权边,最后所有边权就都是1了。不会出现计数问题。
此题应该建立有向图,建立无向图的话边不符合定义了,且统计方案数会出错。
void dfs(int u,int x,int y){
vis[x][y]=1;
for(int i=0;i<8;i++){
int nx=x+dir[i][0],ny=y+dir[i][1];
if(nx>0&&nx<=n&&ny>0&&ny<=m&&!vis[nx][ny]){
if(a[nx][ny]==1) dfs(u,nx,ny);
else if(a[nx][ny]!=2){
vis[nx][ny]=1;
add(u,id[nx][ny]);
}
}
}
}
int st,ed;
int f(int x,int y){
return (x-1)*m+y;
}
bitset<N>in;
ll d[N],p[N];
void spfa(){
queue<int>q;q.push(st);mst(d,0x3f),d[st]=0,p[st]=1;in[st]=1;
while(!q.empty()){
int u=q.front();q.pop();in[u]=0;
for(int i=h[u];i;i=e[i].nt){
int v=e[i].to;
if(d[v]>d[u]+1){
d[v]=d[u]+1;
p[v]=p[u];
if(!in[v]) q.push(v),in[v]=1;
}
else if(d[v]==d[u]+1){
p[v]+=p[u];
}
}
}
if(d[ed]==inf) puts("-1");
else printf("%lld\\n%lld\\n",d[ed]-1,p[ed]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
id[i][j]=f(i,j);
if(a[i][j]==3) st=id[i][j];
if(a[i][j]==4) ed=id[i][j];
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(!a[i][j]||a[i][j]==3) mst(vis,0),dfs(id[i][j],i,j);
spfa();
return 0;
}
P1685 游览
有向无环可重边带权图,给定起点终点,求从起点到终点所有路线的权和+ ( c n t − 1 ) × t 0 (cnt-1)\\times t_0 (cnt−1)×t0, c n t cnt cnt路线数。
DAG(有向无环图) 递推要拓扑排序后递推,不然有的结点信息没收集完全就转移过去了。
void spfa(){
c[st]=1;
queue<int>q;q.push(st);
while(!q.empty()){
int u=q.front();q.pop();
for(int i=h[u];i;i=e[i].nt){
int v=e[i].to,w=e[i].w;
d[v]=(d[v]+d[u]+c[u]*w)%mod;
c[v]=(c[v]+c[u])%mod;
if(!--in[v])
q.push(v);
}
}
d[ed]=(d[ed]+(c[ed]-1)*t0)%mod;
printf("%lld\\n",d[ed]);
}
鸽了…
以上是关于省选图论专题的主要内容,如果未能解决你的问题,请参考以下文章