《算法艺术与信息学竞赛》之 排序与检索 ZOJ1388 Exchanges

Given n integer registers r1, r2, …, rn we define a Compare-Exchange Instruction CE(a, b), where a, b are register indices (1 <= a < b <= n):

CE(a, b)::
if content(ra) > content(rb) then
exchange the contents of registers ra and rb;

A Compare-Exchange program (shortly CE-program) is any nite sequence of Compare-Exchange instructions. A CE-program is called a Minimum-Finding program if after its execution the register r1 always contains the smallest value among all values in the registers. Such program is called reliable if it remains a Minimum-Finding program after removing any single Compare-Exchange instruction.

Given a CE-program P , what is the smallest number of instructions that should be added at the end of program P in order to get a reliable Minimum-Finding program?

Example

Consider the following CE-program for 3 registers:

CE(1, 2); CE(2, 3); CE(1, 2).

In order to make this program a reliable Minimum-Finding program it is sufficient to add only two instructions, CE(1, 3) and CE(1, 2).

Task

Write a program which for each data set:

reads the description of a CE-program,

computes the smallest number of CE-instructions that should be added to make this program a reliable Minimum-Finding program,

writes the result.

Input

The first line of the input contains exactly one positive integer d equal to the number of data sets, 1 <= d <=10. The data sets follow.

Each data set consists of exactly two consecutive lines.

The first of those lines contains exactly two integers n and m separated by a single space, 2 <= n <= 10 000, 0 <= m <= 25 000. Integer n is the number of registers and integer m is the number of program instructions.

The second of those lines contains exactly 2m integers separated by single spaces - the program
itself. Integers aj, bj on positions 2j -1 amd 2j, 1 < j < m, 1 <= aj < bj <= n, are parameters of the j-th instruction in the program.

Output

The output should consist of exactly d lines, one line for each data set.

Line i, 1 <= i <= d, should contain only one integer - the smallest number of instructions that should be added at the end of the i-th input program in order to make this program a reliable Minimum-Finding program.

Sample Input

1
3 3
1 2 2 3 1 2

Sample Output

2

这个题还是非常有水平的,虽然代码量不大,但是思想上要求较高,强烈推荐大家一做。
要解决这道题,首先我么需要几个定义,名字就按照书上说的不改了吧。
先说第一个条件:执行完所给的CE程序后。
首先是孤立,我们称i孤立,即最小值可能在i处。
接着说联通,即最小值不可能在i处。
这个条件下定义了孤立与联通。

接下来是第二个:在执行了少任意一个CE指令后,若最小值不可能在i处,则称i是可靠的。
因为题目要求是在删去任意一条CE指令后仍能保证1处存着最小值,所以我们在执行完所给的CE程序后发现,如果第i个寄存器是可靠的,显然我们不需要再添加CE。
但若第i个是联通的呢?以为第i个只有在执行完完整的CE程序后才能保证最小值不在i,所以为了保证删掉一个CE后最小值仍在i处,我们必须再加上一个CE(1,i),即需要再加上一个操作。
若i是孤立的,我们就必须要加上两个CE(1,i)才能保证了。
所以我们可以得出结论:在执行完CE程序后,当第i个寄存器是可靠状态下时,它对于答案的贡献为零,第i个寄存器是联通状态下时,它对答案的贡献是1,第i个寄存器是孤立状态下时,它对于答案的贡献是2.
那么我们的问题就转化为:在执行完CE程序后,求出每一个寄存器的状态,所以我们需要分析每一个CE(x,y)操作对于寄存器x,y的影响。
注意:CE(x,y)本质是将y中的较小值放入x中。
先来分析对于x的影响:
如果x==1,显然没有影响,因为x是第一个寄存器。否则——
如果x是孤立的,即最小值可能在x处,那么交换后,最小值还是可能在x中,x仍是孤立的,没有影响。否则——
如果y是可靠的,即现在y一定不是最小值,那么显然x该是什么样还是什么样,没有影响。否则——
如果y是孤立的,即最小值可能在y中,那么现在x也变为孤立的
如果y是联通的,即y现在是存着最小值的,那么a现在也联通

对于y的影响简单些:若y是孤立的,现在是联通的,若y是联通的,现在是可靠的,若y是可靠的,现在仍然可靠。

现在我们就分析完了,接下来上代码了,自己写的,网上目前还找不到别人的题解,(立个flag)说不定有一天就火了呢。

#include<cstdio>
#include<cstring>
using namespace std;
int d,n,m,a[10005];//数组a[i]的值为0时表示i是孤立的,1表示联通,2表示可靠 
int main(){
    scanf("%d",&d);
    while(d--){
        memset(a,0,sizeof(a));//数组初始化 
        a[1]=2;//a[1]始终都是可靠的 
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            int x,y;
            scanf("%d%d",&x,&y);
            //对于x寄存器:
            if(x==1)i=i;//此为x为1  ||  x是孤立的  ||  y是可靠的,则不造成影响 
            else if(a[x]==0)i=i;
            else if(a[y]==2)i=i;
            else if(a[y]==0)//若y是孤立的 
                a[x]=0;//是x孤立 
            else if(a[y]==1)//若y是联通的 
                a[x]=1;//x联通 
            //对于y寄存器,影响较小
            if(a[y]!=2)
                a[y]++;
        }
        int ans=0;
        for(int i=1;i<=n;i++)
            ans+=2-a[i];//计算ans
        printf("%d\n",ans); 
    }
    return 0;
}

有什么问题欢迎指出。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值