牛客練習賽26 C 城市規劃【思維】
城市規劃
時間限制:C/C++ 1秒,其他語言2秒 空間限制:C/C++ 262144K,其他語言524288K 64bit IO Format: %lld
題目描述
小a的國家裡有n個城市,其中第i和第i - 1個城市之間有無向道路連線,特殊的,第1個城市僅與第2個城市相連
為了減輕道路維護負擔,城市規劃局局長MXT給出了m個要求,他想讓小a斷開一些道路,使得任意1 ≤ i ≤ m ,城市xi不能到達城市yi
同時最小化斷開道路的數量。
輸入描述:
第一行兩個整數n, m,分別表示城市的數量和請求的數量 接下來m行,每行兩個整數x,y,表示需要使得x不能到達y
輸出描述:
輸出一個整數,表示最小斷開橋的數量
示例1
輸入
4 2
1 3
2 4
輸出
1
說明
可以斷開(2, 3)城市之間的道路
示例2
輸入
4 3
1 3
2 4
1 2
輸出
2
說明
可以斷開(1, 2) (2, 3)之間的道路
備註:
對於100%的資料:n ≤ 106, m ≤ 107 本題不卡常數,請設計嚴格線性做法
讀入檔案較大,請使用讀入優化,本機除錯時請使用檔案輸入輸出 #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++) char buf[(1 << 22)], *p1 = buf, *p2 = buf; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } 用法: int a = read(), b = read(); std::cout << a + b;
由於nowcoder的編譯器限制,如果需要在程式中開107級別的陣列,可能會出現記憶體超限的情況,請使用new函式手動申請 用法: int* P = new int[(int)1e7 + 10];
題解:首先需要讀入優化。程式flag[y]標記結點y是否在查詢中出現,pos[y]記錄要使y和對應的x斷開至少要從什麼位置之後斷開一條邊,例如x和y分別為1和4,那麼pos[4]=1表明至少要從1編號之後選擇一條邊,由於y值可能相同,因此程式有取pos[y]的較大值的操作。l 記錄上次斷掉的邊的位置,初始化為0,對於當前的y如果pos[y]>=l表明必須再斷掉一條邊才能滿足x和y不連通,此時更新答案和l的值
AC的C++程式碼:
#include<iostream>
using namespace std;
//讀入優化
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<22,stdin),p1 == p2)?EOF:*p1++)
char buf[(1<<22)],*p1=buf,*p2=buf;
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c == '-') f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c = getchar();}
return x * f;
}
const int N=1000010;
bool flag[N];//標記y出現的位置
int pos[N];//pos[y]記錄要使得y和對應的x斷開至少要在哪個結點編號
int main()
{
int n,m,x,y;
n=read(),m=read();
while(m--){
x=read();
y=read();
flag[y]=true;
pos[y]=max(pos[y],x);
}
//線性掃描
int l=0,ans=0;
for(int i=1;i<=n;i++)
if(flag[i]&&pos[i]>=l){
l=i;
ans++;
}
printf("%d\n",ans);
return 0;
}