Codeforces 421D Giving Awards 策略题

来源:互联网 发布:列主元三角分解法C语言 编辑:程序博客网 时间:2024/06/14 07:46

题目大意:

就是现在要求一个长度为n的排列, 使得这个排列中不出现给定的m组相邻位置情况, 输出任意一组解


大致思路:

策略题...YY能力还是不够...

策略见代码注释吧


代码如下:

Result  :  Accepted     Memory  :  5408 KB     Time  :  93 ms

/* * Author: Gatevin * Created Time:  2015/2/24 18:19:34 * File Name: poi~.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;#define mp(x, y) make_pair(x, y)int n, m;map<pair<int, int>, bool> M;//map记录相邻顺序是否禁止int last[30010], next[30010];/* * 策略题, 先建立一个虚拟节点0, 下面紧跟数1, 以链表的形式保存, 然后依次插入2~n * 插入i时, 先判断能否插在队尾, 如果可以直接插在队尾, 否则向前寻找直到前面的数可以放在这个数的前面1位 * 将这个数插入这个位置, 这样是一定可行的, 因为找到这个数是因为其后面的数p与需要插入的数矛盾, 即存在禁止(p, q) * 那么一定没有禁止(q, p)(题意说过) * 所以这样插入不会产生矛盾 */int main(){    scanf("%d %d", &n, &m);    int ta, tb;    memset(last, 0, sizeof(last));    memset(next, 0, sizeof(next));    for(int i = 1; i <= m; i++)        scanf("%d %d", &ta, &tb), M[mp(ta, tb)] = 1;    next[0] = 1, last[1] = 0;//链表需要的每个结点的两个指针    int tail = 1;    for(int i = 2; i <= n; i++)    {        if(!M[mp(tail, i)])        {            next[tail] = i;            last[i] = tail;            tail = i;            continue;        }        int tmp = tail;        while(M[mp(tmp, i)])            tmp = last[tmp];        last[next[tmp]] = i;        next[i] = next[tmp];        next[tmp] = i;        last[i] = tmp;    }    int now = 0;    while(next[now])//输出链表即可        printf("%d ", next[now]), now = next[now];    return 0;}


0 0
原创粉丝点击