文号
t34007
阅读
8186
回复
5
收藏
2
《神秘的水井》解题报告 - By LTL
2011/06/04
IP:福建
前一段时间做的一道题目,感觉思维很精妙,发上来与大家共享

题意简述:
n个白点和n个黑点,如果异色点曼哈顿距离不超过C则黑向白连边,否则白向黑连边,同色点的连边方向自定,问最少和最多有多少个异色三度环。
n≤100000。

关键字:线段树,三角形计数

算法描述:
将每个点的控制范围旋转45°,则对于每个点,来自异色点的入度可以通过线段树维护扫描线求矩形内的点数求出。对于两个同色点,从入度少的连向入度多的点可以使得三角形最少(例如对于两个白点ab,在a控制范围内的黑点全部向a连边,且b向这些点连边,则如果从a向b连边,这些点就会被加入答案),反之则为最大值,这样我们就可以求出两种答案所对应方案下每个点的入度。
接下来就是统计答案的问题了,由于三度环不好考虑,所以我们考虑其补集——同向三角形,即存在一个顶点使得在这个三角形中有两条边作为该点的入度。这样的三角形可以靠枚举一个点,求在入度中任选两条边的组合数得到。注意:无论是求总数还是求同向三角形,都要减去同色三角形的部分。

分析&总结:
带有组合数的题目要想清楚了将公式写下,敲完代码还要认真核对一遍!
本题容易想到直接去扣除两个矩形相交部分的点求解,但是这样很麻烦。用三角形计数的方式重新计算答案可以很好地解决这个问题。

My Code:

/*
Title: Triangle
Author: LTL
*/

#include <iostream>
#include <memory.h>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>

#define InputFileName        "XXXXXXX"
#define OutputFileName        "Data.out"

using namespace std;

const int MaxN = 1100000, oo = 1000000000, QLen = MaxN, MaxM = 20;

int n, m, Queue[QLen+1], QHead, QTail, a[MaxM], Path[MaxN], f[MaxN], Ans[MaxN], Total;
bool Flag[MaxN];

void Init()
{
    cin >> n >> m;
    for (int i = 1; i <= m; ++i)
        cin >> a[i];
    sort(a+1, a+m+1);
}

void SPFA()
{
    memset(Path, 127, sizeof(f[0])*n);
    memset(Flag, 0, sizeof(Flag[0])*n);
    QHead = QTail = 0;
    Queue[++QTail] = 0;
    for (int t, i, v; QHead < QTail;)
        for (t = Queue[++QHead], i = 1; i <= m; ++i)
            if (! Flag[v = (t*10+a[i]) % n] && (Path[t] < oo || a[i]))
            {
                Path[v] = t;
                f[v] = a[i];
                Flag[Queue[++QTail] = v] = 1;
            }
}

void Print()
{
    Total = 0;
    int i;
    for (i = 0; Path[i] && Path[i] < oo; i = Path[i])
        Ans[++Total] = f[i];
    if (Path[i] < oo)
        Ans[++Total] = f[i];
    else
        printf("0");
    for (; Total; --Total)
        printf("%d", Ans[Total]);
    printf("\n");
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen(InputFileName, "r", stdin);
    freopen(OutputFileName, "w", stdout);
    #endif
    int TestCase;
    for (cin >> TestCase; TestCase; --TestCase)
    {
        Init();
        SPFA();
        Print();
    }
    return 0;
}
+500
科创币
joyeep
2011/06/04
支持算法贴
-5000
科创币
科创网
2011/06/05
兑换学术分
+1
学术分
科创网
2011/06/05
兑为学术分
来自:
软件综合
5
ltl作者
15年7个月前IP:未同步
298134
1楼
三角形计数问题中的补集转化思想应该也算是种挺常见的思想吧
引用
评论
ltl作者
15年7个月前IP:未同步
298221
2楼
还是没人理………………今晚做GCJ去……
引用
评论
15年7个月前IP:未同步
298262
3楼
LZ 你尽量发表,无须顾虑,届时把你帖子作一个专题
引用
评论
ltl作者
15年7个月前IP:未同步
298273
4楼
好吧,多谢了
引用
评论
笔记
{{note.content}}
{{n.user.username}}
{{fromNow(n.toc)}} {{n.status === noteStatus.disabled ? "已屏蔽" : ""}} {{n.status === noteStatus.unknown ? "正在审核" : ""}} {{n.status === noteStatus.deleted ? '已删除' : ''}}
  • 编辑
  • 删除
  • {{n.status === 'disabled' ? "解除屏蔽" : "屏蔽" }}
我也是有底线的