POJ 1033 模拟

//11158197	c00h00g	1033	Accepted	672K	454MS	G++	1947B	2013-01-04 22:40:37
//几十天没看,回过头来,终于想通了
//我没有处理环的情况
//假设有这样一组数据,1->2,2->3,3->4,4->1,排列应该为 4 1 2 3(输入),我们的做法应该是将1234放入栈中,然后出栈将
//4放到从后找出来的一块空的区域,剩下的123组成了链,只需要将3->4,2->3,1->2就可以了 
#include<cstdio>
#include<cstdlib>
#include<stack>
#include<string.h>
using namespace std;

stack<int> st;
//p[i]表示放在i位置上的数据应该放在哪个位置 
int p[10005];
int N,K,n;
int i,j;
 
int main(){
    while(scanf("%d%d",&N,&K)!=EOF){
        int num=1,pos;
        memset(p,-1,sizeof(p));
        while(K--){
            scanf("%d",&n);
            for(i=0;i<n;i++){
                scanf("%d",&pos);
                p[pos]=num++;
            }
        }
        
        int start;
        bool flag=false;
        for(i=1;i<=N;i++){
            if(p[i]==i||p[i]==-1)
                continue;
            flag=true;
            start=j=i;
            while(p[j]!=start&&p[j]!=-1){
                st.push(j);
                j=p[j];
            }
            if(p[j]==-1){
                int begin;
                int to=j;
                while(!st.empty()){
                    begin=st.top();st.pop();
                    printf("%d %d\n",begin,to);
                    p[to]=to;
                    to=begin;         
                }
                p[begin]=-1;
            }else if(p[j]==start){
                st.push(j);
                int begin,to;
                for(int k=N;k>=1;k--){
                    if(p[k]==-1){
                        to=k;
                        break;
                    }
                }
                int count=1;
                while(!st.empty()){
                    begin=st.top();st.pop();
                    printf("%d %d\n",begin,to);
                    if(count==1){
                        p[to]=start;
                    }else{
                        p[to]=to;
                    }
                    to=begin;
                    count++;
                }
                p[begin]=-1;
            }
        }
        if(flag==false)
            printf("No optimization needed\n");
    }            
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值