Summer day 12

本文解析了UVA竞赛中的三道题目,包括网络流最大流问题、双向队列模拟问题及带权并查集问题。提供了详细的代码实现及解题思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天的训练题。
A。有关网络流的最大流问题,并不懂。

UVA 753 A Plug for UNIX

这里写图片描述

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
using namespace std;
typedef char str[31];
const int N=105;
const int MAX=2147483647;
int T,tot,n,m,q,i,j,l,r,u,v,ans,sum,head[N<<3],Next[N*N],go[N*N],cost[N*N],down[N*N],b[N*N],d[N<<3];
str s1,s2,s[N<<3];
inline int S(int a,int b) { return (a<b)?a:b; }
inline void Add(int u,int v,int t)
{   Next[++l]=head[u],head[u]=l,go[l]=v,cost[l]=t,down[l]=l+1;
    Next[++l]=head[v],head[v]=l,go[l]=u,cost[l]=0,down[l]=l-1;
}
inline int Find(str A)
{   if (r==0) { strcpy(s[r=1],A); return r; }
    for (int i=1;i<=r;i++)
        if (strcmp(s[i],A)==0) return i;
    strcpy(s[++r],A);
    return r;
}
inline bool bfs()
{   int l,r,j; b[l=r=1]=0; memset(d,-1,sizeof(d)); d[0]=0;
    while (l<=r)
    {   for (j=head[b[l]];j;j=Next[j])
            if ((cost[j])&&(d[go[j]]==-1)) d[go[j]]=d[b[l]]+1,b[++r]=go[j]; l++;
        } if (d[800]>0) return true; return false;
}
inline int dinic(int st,int tk)
{   if (st==800) return tk; int wc=tk,j,kcm; 
    for (j=head[st];j&&tk;j=Next[j])
     if ((d[go[j]]>d[st])&&(cost[j]))
     {  kcm=dinic(go[j],S(tk,cost[j]));
        cost[j]-=kcm; cost[down[j]]+=kcm; tk-=kcm;
        }
    return wc-tk;
}
int main()
{   freopen("A.in","r",stdin);
    freopen("A.out","w",stdout);
    for (scanf("%d",&T),tot=1;tot<=T;tot++)
    {   memset(head,0,sizeof(head));
        if (tot>1) printf("\n");
        scanf("%d",&n),l=ans=r=0;
        for (i=1;i<=n;i++) 
        {   scanf("%s",s1);
            u=Find(s1);
            Add(u,800,1);
            }
        scanf("%d",&m);
        for (i=1;i<=m;i++)
        {   scanf("%s%s",s1,s2);
            u=Find(s1),v=Find(s2);
            Add(u,v,1),Add(0,u,1);
            }
        scanf("%d",&q);
        for (i=1;i<=q;i++) 
        {   scanf("%s%s",s1,s2);
            u=Find(s1),v=Find(s2);
            Add(u,v,MAX);
            }
        while (bfs()) while (sum=dinic(0,MAX)) ans+=sum; 
        printf("%d\n",m-ans);
        }
    return 0;
}

C, 双向队列模拟。同看不懂。

UVA 732 Cat

给定source及target字符串
Source、target长度一样
两个操作
从source首位置开始,字符可以在栈sc中进行入栈,入栈后source中此字符串被去掉,为了方便深搜,用deque(dc)来保存source。记操作为i。
从sc出栈到新字符串stem,如果可以组成target,则为可行解,输出对栈。记操作为o。
注意事项
可以从sample观察到,要从source获得target,第一个对栈操作必为I(因此由i进入dfs),最后一个对栈操作必为I(因此由i操作后中寻找可行解)。
为了按字典序输出,因此按字典序搜索。

HDU 3047 Zjnu Stadium

题意:有一个体育馆,座位呈环状,每一列有300个座位,按逆时钟方向编号为1~300,假设行数无穷大。
某一天,有N个人来到这个体育馆看一场赛事,主办方提出了M个要求,要求的格式是“A B X”,表示的是,假设A坐在编号为i的列,则B必须坐在编号为(i+x)的列上。
这些要求里有一些是错误的,只有和前面的要求产生冲突时才算错误,其它都是正确的。程序要输出错误的要求个数。

分析:带权并查集
对于并查集中的每一棵数, 树根的距离为0,然后以树根作为参照,每个结点的权值代表与树根的距离。
合并A,B时,假设A,B属于不同的树,那么就要合并这两棵树, 把A树合并到B树上,这时要给A树的跟结点root_a赋值,关键是给root_a附上一个什么值。 由于A点和B点的权值rank[A]和rank[B]都是相对跟结点的距离,所以分析A,B之间的相对距离,可以得到rank[root_a] = rank[A]+x-rank[B]。 注意到这时,对于原来的A的树,只跟新了root_a跟结点的权值, 那么其它结点的更新在查找的那一步里面实行了。
这里写图片描述
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值