NOI2016江蘇省選Day2T1 詳解

2021-07-11 13:14:55 字數 3356 閱讀 8975

jstsc-day2t1: airport 解題報告

【問題描述(大意)】

jsoi王國有n個機場,m條直達航班。每兩個機場之間都有乙個固定的飛行時間。由於流量控制,氣候,地形等因素,從i到j的飛行時間與從j到i的飛行時間不一定相等。飛機每降落在某一機場,都需要例行檢查,維護,加油。在第i座機場維護的時間為pi。

作為jsoi航空公司的金牌客戶,jyy發現jsoi航空公司並沒有用m架飛機執行這m條航班。因為jsoi航空公司可以開闢一些臨時航班,讓一些飛機先後執行多條航班任務。現在給定m條航班的起飛地點,降落地點和起飛時間,jyy希望算出至少需要幾架飛機才能完成航班任務。

【輸入資料】

第一行:兩個正整數n和m;

第二行:n個非負整數,其中第i個數表示在第i座機場維護的時間;

下面n行每行n個非負整數,其中第i行第j個表示從第i座機場飛到第j座機場所需的時間,輸入資料保證第i行第i個為0;

下面m行每行3個整數,分別為每條航線的起飛機場編號,降落機場編號和起飛時間;

【輸出資料】

僅一行,表示完成所有航班所需的最少飛機數

【樣例輸入1(自編,僅供參考)】

3 3100 1 1

0 1 2

4 0 3

2 1 0

2 3 1

3 1 2

2 1 7

【樣例輸出1】

【樣例輸入2(自編,僅供參考)】

3 3100 1 1

0 1 2

4 0 3

2 1 0

2 3 1

3 1 2

2 1 6

【樣例輸出2】

【樣例說明】

對於第一組資料,在1時刻用一架飛機執行第一條航線。在2時刻用一架飛機執行第二條航線。第一架飛機執行完航線後,開闢一條臨時航線從機場3到機場2,在7時刻再用第一家飛機執行第三條航線。共需要兩架飛機。

對於第二組資料,第一架飛機執行完航線後,要在7時刻才能開始執行第三條航線。而第三條航線要在6時刻執行,所以只能用三架飛機,每架執行一條航線。

【資料規模】

對於30%的資料,n, m≤10;

對於100%的資料,n, m≤500;

【演算法分析】 這題

30%的資料並不好騙,還不如直接想滿分演算法。(/(ㄒ

oㄒ)/~~)

乙個簡單易想的技巧是把在每個機場維護的時間加到以此機場終點的邊權上。因為如果想讓飛機繼續飛行,這個維護時間是省不了的。這樣可以算出每趟航班所需的時間。

然後跑一遍

floyd

求每兩點之間的最短路徑。

[o(n3)

的效率並不知道為什麼不會炸。。。]

將m條航線抽象成

m個點。這樣對於航線

i和航線

j,如果執行完航線

i之後來得及再去執行航線

j,就在第

i個點和第

j個點之間連一條有向邊。

這樣就將問題轉化成了乙個圖的最小鏈覆蓋問題。我們可以這樣做:如果執行完第

i個任務後來得及去執行第

j個任務,就在節點

i和節點

j之間連一條邊。如果最初用

n架飛機分別執行這

n個任務,那麼挑中一條邊就可以省一架飛機。於是問題轉化為了二分圖的最大匹配。

當然,可以用網路流解決。但是用匈牙利演算法更簡潔更快。這樣整個程式的時間複雜度是

floyd

的複雜度

o(n3)

,因為n

≤500

,所以能過。

【參考程式】

#include

#include

#include

#include

usingnamespace std;

structnode

int start;

int end;

int    time;

int need;

}route[501];

boolcompare(node x,node y)

return x.timeint n,m;

intga[501][501];

intp[501];

booldata[501][501];

boolstate[501];

intresult[501];

boolfind(int num)

int i;

for (i=1;i<=n;i++)

if (data[num][i] &&!state[i])

state[i]=true;

if (result[i]==0 ||find(i))

result[i]=num;

returntrue;

return false;

int main()

freopen("airport.in","r",stdin);

freopen("airport.out","w",stdout);

scanf("%d%d",&n,&m);

int i,j,k;    

for (i=1;i<=n;i++)scanf("%d",&p[i]);

for (i=1;i<=n;i++)

for (j=1;j<=n;j++)

scanf("%d",&ga[i][j]);

ga[i][j]+=p[j];

for (i=1;i<=m;i++)

scanf("%d%d%d",&route[i].start,&route[i].end,&route[i].time);

route[i].need=ga[route[i].start][route[i].end];

for (k=1;k<=n;k++)

for (i=1;i<=n;i++)

for(j=1;j<=n;j++)

if (i!=j&& i!=k && j!=k)

if(ga[i][k]+ga[k][j]sort(route+1,route+m+1,compare);

memset(data,false,sizeof(data));

for (i=1;i<=m-1;i++)

for (j=i+1;j<=m;j++)

if(route[i].time+route[i].need+ga[route[i].end][route[j].start]<=route[j].time)

data[i][j]=true;

int ans=0;

for (i=1;i<=n;i++)

memset(state,false,sizeof(state));

if(find(i)) ans++;

ans=m-ans;

printf("%d",ans);

return 0;

2017江蘇省賽賽後感想

江蘇省賽感想 凌曉此次江蘇省賽,心情比較激動,a題時頭腦不是很清醒,很冷靜,但是組織安排還是比較合理,a題本來以為是水題,但看完題目以後覺得不簡單,於是,此時沒有過多的去糾結a題,隊友們果斷跟榜,a出兩題。我在一邊想a題,後來覺得自己演算法會t就放棄了。然後一起在想h,e題,h題一開始有點想法,但是...

江蘇省 領航杯部分wp

只能說這比賽平台 題目 簡單記錄一下,畢竟自己也做了好久 開啟程式是下黑白棋,要戰勝ai才能獲得flag。利用ollydebug開啟,找到跳入,單步步入真正的程式,然後中文搜尋得到flag。利用ida開啟能夠很清楚的看明白邏輯,encode函式和judgement函式都是註明了的。base加密自定義...

2017 江蘇省賽JSCPC H 貪心,prim

給你一棵樹,兩兩節點間有乙個距離ci c i,現在要重建地圖,任意兩個頂點間的花費是他們之間的最短路,建最大生成樹求花費.這題比賽的時候沒有做出來,賽後看題解原來很簡單,想象prim的建樹過程每次找剩餘邊集合中的最大距離.顯然我們首先找到直徑v0 v1 v0,v1 肯定作為第一條邊然後照剩餘點,對於...