UVALive7462 ——Work problem(读题能力很重要)

UVALive 7462 ——Work problem(读题能力很重要)
题目链接:题目链接

题目开头:Raymond is a big data analyst. He constructs a social network G from n persons numbered 1, 2, … , n.
For two groups of persons G1 and G2 , he utilizes the following two rules to construct the network:
Rule 1: If two persons p1 ∈ G1 and p2 ∈ G2 have a common interest, then G1 and G2 can be mergedinto one group by connecting every person in G1 to all the persons in G2. This construction is
called the join operation, denoted by G1⊗G2. For each person p1 ∈ G1 and p2 ∈ G2, we saythat p1 and p2 have a connecting relation after applying Rule 1.
Rule 2: If any two persons p1 ∈ G1 and p2 ∈ G2 have no common interest, then no connecting
relation is created between G1 and G2. This construction is called the union operation, denoted
by G1∪G2。。。
详细题目描述见题目链接pdf。

吐槽:这绝对是我做过的最难读的题了,没有之一~~。

题目大意:现定义对点集的两种操作J和U。设现有两个图A,B(不一定连通),J操作是将A中的每一个点与B中的每一个点连一条边,并将结果变为新图C;U操作是将A,B两个图直接放到一起变为新图C(不连任何新边)。先给出一个用J,U与节点编号表示的图,现在要求对每一个点分配权值,并满足对于任意两个点,如果它们的权值相等(w[i]==w[j]),则在他们之间的每条路径上,都至少有一个点k的权值大于他们俩的权值(w[k]>w[i]==w[j])。现在要求对整个图分配权值后,最大的权值最小是多少(从1开始分配)。

题解:通过研究样例可以发现,本题与J操作关系很大。准确的说,对于两个图A,B进行J操作时,设其中的的编号的最大值分别为Amax,Bmax,节点个数分别为Anum,Bnum,则对于合并之后的图C,Cmax = min((Amax+Bnum),(Anum+Bmax)),Cnum = Anum + Bnum。而进行U操作时,Cmax=max(Amax,Bmax),Cnum=Anum+Bnum。所以只需按照输入的顺序进行合并,并在合并时计算结果即可。

代码如下:

#include  <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn = 1e5+10;
struct Point{
    int minv;
    int cntnode;
    Point join(const Point& w){
        Point a,b;
        a.minv = w.minv + cntnode;
        a.cntnode = cntnode +w.cntnode;
        b.minv = minv + w.cntnode;
        b.cntnode = cntnode +w.cntnode;
        if(a.minv<b.minv) return a;
        else return b;
    }
    Point unjoin(const Point& w){
        Point a;
        a.minv=max(minv,w.minv);
        a.cntnode = cntnode + w.cntnode;
        return a;
    }
    void print()
    {
        printf("minv: %d  cntnode: %d \n",minv,cntnode);
    }
    Point() {minv=0;cntnode=0;}
};
char s[maxn];
int n,all_point=1;
Point dfs(int from)
{
    Point v,w;//v.print();
    int flag = 0;
    for(;;){
        all_point++;
        int i = all_point;
        while(s[i]>='0' && s[i]<='9') {
            v.minv=1;
            v.cntnode=1;
            all_point++;i=all_point;
        }
        if(s[i]=='J') {
            w = v;
            flag = 1;
        }
        if(s[i]=='U') {
            w=v;
            flag = 2;
        }
        if(s[i]==')') {
            if(flag == 0) {return v;}
            else if(flag  == 1) return v.join(w);
            else if(flag == 2) return v.unjoin(w);
        }
        if(s[i]=='(') v = dfs(all_point);
    }
}

int main()
{
    freopen("A.in","r",stdin);
    freopen("A.out","w",stdout);
    int kase;scanf("%d",&kase);
    while(kase--){
        scanf("%d",&n);
        scanf("%s",s);
        int lens = strlen(s);
        for(int i=lens;i>=1;i--) s[i]=s[i-1];
        s[0]='(';s[lens+1]=')';s[lens+2]='\0';
        all_point=0;
        Point ans = dfs(0);
        printf("%d\n",ans.minv);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值