220512总结
220512总结
我像是对 DFS 有什么执念(
又因为忘关注释的 freopen 暴了个零
因为 sort(col+1,col+N+1)
第二项忘写了那个 \(1\) 挂了 \(10\) 分
因为跑 dfs 忘了记录这个点到没到过导致一个点超时
因为忘开 long long
挂掉 \(10\) 分
寄!
T1 火车票
不太清楚怎么做出来的 大概是dp罢
从始点开始到终点,每一个点都向后更新可以到达的所有点的最小花费
dp[s] = 0;
for(int i = s;i<t;i++){
for(int j = i+1;j<=t;j++){
if(len(i,j) > l3) break;
dp[j] = min(dp[j],dp[i]+ct(i,j));
}
}
T2 最优乘车
图论
建边的时候让这条边的边权等于公交编号
这样遍历图的时候一旦两条边边权不同就相当于换乘了
//dfs(当前点/边的编号,目前换乘次数,上条边的边权)
void dfs(int k,int num,int col){
if(k == N){
cnt = min(num,cnt);
return;
}
if(vis[k]) return;
vis[k] = 1;
for(int i = head[k];i;i = edge[i].nxt){
if(edge[i].w == col){
dfs(edge[i].to,num,col);
}
else{
dfs(edge[i].to,num+1,edge[i].w);
}
}
}
T3 刻录光盘
还是图论
读入的时候将点按照 【入度越少,出度越多】越靠前 的顺序排序
这样越靠前的点,在dfs树上的位置也就越靠近根部,越有可能以它开始
然后以每一个点为起点跑一遍dfs,将点染成不同颜色
相同的颜色的点只需要一张光盘
最后数有多少种颜色即可
#include<bits/stdc++.h>
using namespace std;
#define FO(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout)
const int maxN = (1e5+10);
struct Edge{
int to,nxt;
}edge[maxN];
int head[maxN];
int tot;
inline void add_edge(int u,int v){
edge[++tot].to = v;
edge[tot].nxt = head[u];
head[u] = tot;
}
int N;
int col[maxN];
struct D{
int RD,CD;
int ID;
friend bool operator < (D A,D B){
if(A.RD != B.RD) return A.RD < B.RD;
return A.CD > B.CD;
}
}ds[maxN];
int coln;
int cnt;
void dfs(int k){
if(col[k]) return;
col[k] = coln;
for(int i = head[k];i;i = edge[i].nxt){
dfs(edge[i].to);
}
return;
}
int main(){
// FO("cdrom");
scanf("%d",&N);
for(int i = 1;i<=N;i++){
int t;
ds[i].ID = i;
while(1){
scanf("%d",&t);
if(!t) break;
add_edge(i,t);
ds[t].RD++;
ds[i].CD++;
}
}
sort(ds+1,ds+N+1);
for(int i = 1;i<=N;i++){
int j = ds[i].ID;
if(col[j]) continue;
coln++;
dfs(j);
}
sort(col+1,col+N+1);
for(int i = 1;i<=N;i++){
// printf("%d ",col[i]);
if(col[i] != col[i-1]) cnt++;
}
printf("%d",cnt);
return 0;
}
T4 最短路径
直接套 \(\operatorname{SPFA}\) 就行了吧
不过读入稍微麻烦一点
我是靠读入字符串后判断总位数和第一位是不是负号来判断这是个数还是个单符号