14997: [Usaco2017 Feb]Why Did the Cow Cross the Road III

目录

特别提示

网址

题目(一本通版)

    【题目描述】

    【输入】

    【输出】

    【输入样例】

    【输出样例】

能过的解法

    题目理解

    解题策略

          1. 初始化网格与道路:

           2. 处理道路信息:

           3. 应用并查集:

            4. 计算“遥远”对:

    代码

有趣的解法


特别提示

本人有两种解法,第一种比较笨,第二种一秒即可。

网址

一本通:点此进入

bzoj:没找到这题,服了

洛谷:点此进入

题目(一本通版)


时间限制: 1000 ms         内存限制: 262144 KB
提交数: 27     通过数: 9

    【题目描述】

Why did the cow cross the road? Well, one reason is that Farmer John's farm simply has a lot of roads, making it impossible for his cows to travel around without crossing many of them.

FJ's farm is arranged as an N×N square grid of fields (2 <= N <= 100), Certain pairs of adjacent fields (e.g., north-south or east-west) are separated by roads, and a tall fence runs around the external perimeter of the entire grid, preventing cows from leaving the farm. Cows can move freely from any field to any other adjacent field (north, east, south, or west), although they prefer not to cross roads unless absolutely necessary.

There are K cows (1 <= K <= 100, K <= N^2) on FJ's farm, each located in a different field. A pair of cows is said to be "distant" if, in order for one cow to visit the other, it is necessary to cross at least one road. Please help FJ count the number of distant pairs of cows.

    【输入】

The first line of input contains N, K, and R.

The next R lines describe R roads that exist between pairs of adjacent fields.

Each line is of the form r c c r' c'(integers in the range 1…N)

indicating a road between the field in (row r, column c) and the adjacent field in (row r',column c').

The final K lines indicate the locations of the K cows, each specified in terms of a row and column.

    【输出】

Print the number of pairs of cows that are distant.

    【输入样例】

3 3 3
2 2 2 3
3 3 3 2
3 3 2 3
3 3
2 2
2 3

    【输出样例】

2

能过的解法

    题目理解

题目描述了一个农场地图问题,地图以N×N的网格形式展现,其中一些相邻格子之间由道路分隔。每对相邻格子若未被道路分割,则默认可直接通行。问题要求计算K头分布在不同格子上的牛中,“遥远”对的数量,即至少需要跨越一条道路才能相遇的牛对数。

    解题策略

          1. 初始化网格与道路:

 •我们可以想象一个初始状态,每个格子都能与其上、下、左、右四个方向的格子自由通行(除非有道路阻隔)。可以使用一个二维数组来表示网格,额外的结构(如并查集)来管理连通性。

           2. 处理道路信息:

•根据输入的R条道路信息,对相应的网格格子间的连通性进行调整。例如,如果输入表示在(2,2)和(2,3)间有一条路,那么在并查集中,这两格应当被视为不再直接连通。

           3. 应用并查集:

•并查集是一种常用的数据结构,能够高效处理集合的合并与查询问题。在这个场景中,它可以帮助我们快速判断任意两格是否属于同一个连通分量。随着道路信息的加入,我们会逐步合并那些在物理上可直接到达的格子集合。

            4. 计算“遥远”对:

•对于每一对牛的位置,利用并查集检查它们是否属于不同的集合(即不连通)。如果是,说明这对牛至少需要经过一次道路才能见面,因此计数加一。遍历所有牛的组合来统计总数。

    代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <utility>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 110
#define pa pair<int,int>
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,K,m,a[N][N],dx[]={0,0,1,-1},dy[]={1,-1,0,0},ans=0;
bool f[N][N][4],vis[N][N];
struct P{
    int x,y;
}st[N];
inline int bfs(int id){
    queue<pa>q;memset(vis,0,sizeof(vis));int res=0;
    q.push(make_pair(st[id].x,st[id].y));vis[st[id].x][st[id].y]=1;
    while(!q.empty()){
        int x=q.front().first,y=q.front().second;q.pop();res+=a[x][y];
        for(int k=0;k<4;++k){
            if(f[x][y][k]) continue;
            int xx=x+dx[k],yy=y+dy[k];
            if(xx<1||xx>n||yy<1||yy>n||vis[xx][yy]) continue;
            q.push(make_pair(xx,yy));vis[xx][yy]=1;
        }
    }return res;
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();K=read();m=read();
    while(m--){
        int x=read(),y=read(),x1=read(),y1=read();
        if(x>x1) swap(x,x1);if(y>y1) swap(y,y1);
        if(x==x1){f[x][y][0]=1;f[x][y1][1]=1;}
        else f[x][y][2]=1,f[x1][y][3]=1;
    }for(int i=1;i<=K;++i) st[i].x=read(),st[i].y=read(),a[st[i].x][st[i].y]=1;
    for(int i=1;i<=K;++i) ans+=K-bfs(i);
    printf("%d\n",ans>>1);
    return 0;
}

有趣的解法

看到why(为什么),我就想到了因为他善。

答:因为他善

不过由于不够长无法提交所以应该是:

答:“因为他善。”

标点符号不能丢。

可惜没过。

服了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值