洛谷B3647 【模板】Floyd
思路:
floyd的板子题
代码:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 110;
int dist[N][N], n, m;
void floyd()
{
for (int k = 1; k <= n; k ++)
for (int i = 1; i <= n; i ++)
{
for (int j = 1; j <= n; j ++)
{
for (int k = 1; k <= n; k ++)
dist[j][i] = min (dist[j][i], dist[j][k] + dist[k][i]);
}
}
}
int main()
{
cin >> n >> m;
memset(dist, 0x3f, sizeof dist);
for (int i = 1; i <= n; i ++ )
{
dist[i][i] = 0;
}
while(m--)
{
int u, v, w;
cin >> u >> v >> w;
dist[u][v] = dist[v][u] = min(dist[v][u], w);
}
floyd();
for (int i = 1; i <= n; i ++)
{
for (int j = 1; j <= n; j ++)
{
cout << dist[i][j] << ' ';
}
puts("");
}
return 0;
}
洛谷P4779 【模板】单源最短路径(标准版)
思路:
dijkstra的板子题,我背的这个板子有点问题,只能过两个样例。(过段时间再补吧)
代码:
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
typedef pair<int,int>PII;
const int N=150000;
bool st[N];
int dist[N],w[N];
int e[N],ne[N],h[N],idx;
int n,m,s;
void add(int a,int b,int c)
{
w[idx]=c;
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void dijkstra()
{
dist[1]=0;
priority_queue<PII,vector<PII>,greater<PII>>heap;
heap.push({0,1});
while(heap.size())
{
PII t=heap.top();
heap.pop();
int ver=t.second,distance=t.first;
if(st[ver])continue;
st[ver]=true;
for(int i=h[ver];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>distance+w[i])
{
dist[j]=distance+w[i];
heap.push({dist[j],j});
}
}
}
}
int main()
{
memset(dist,0x3f,sizeof dist);
memset(h,-1,sizeof h);
cin>>n>>m>>s;
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
}
dijkstra();
for(int i = 1; i <= n; i ++)
{
cout << dist[i] << ' ';
}
return 0;
}
洛谷P2661 [NOIP2015 提高组] 信息传递
思路:
并查集求最小环
代码:
#include<cstdio>
#include<iostream>
using namespace std;
const int N = 2e5+10;
int f[N],d[N],n,minn,last;
int fa(int x)
{
if (f[x]!=x)
{
int last=f[x];
f[x]=fa(f[x]);
d[x]+=d[last];
}
return f[x];
}
void check(int a,int b)
{
int x=fa(a),y=fa(b);
if (x!=y) {f[x]=y; d[a]=d[b]+1;}
else minn=min(minn,d[a]+d[b]+1);
return;
}
int main()
{
int i,t;
scanf("%d",&n);
for (i=1;i<=n;i++) f[i]=i;
minn=0x3f3f3f3f;
for (i=1;i<=n;i++)
{
scanf("%d",&t);
check(i,t);
}
printf("%d",minn);
return 0;
}
洛谷
思路:
spfa的板子题
代码:
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn=1e6+10,maxm=2e6+10,INF=0x3f3f3f3f,MOD=100003;
vector<int>G[maxn];int dep[maxn];bool vis[maxn];int cnt[maxn];
int main(){
int N,M;scanf("%d%d",&N,&M);
for(int i=1;i<=M;i++){
int x,y;scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
queue<int>Q;dep[1]=0;vis[1]=1;Q.push(1);cnt[1]=1;
while(!Q.empty()){
int x=Q.front();Q.pop();
for(int i=0;i<G[x].size();i++){
int t=G[x][i];
if(!vis[t]){vis[t]=1;dep[t]=dep[x]+1;Q.push(t);}
if(dep[t]==dep[x]+1){cnt[t]=(cnt[t]+cnt[x])%MOD;}
}
}
for(int i=1;i<=N;i++){
printf("%d\n",cnt[i]);
}
return 0;
}
洛谷P3367 【模板】并查集
思路:
模板题😬
代码:
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int p[N];
int n, m;
int find(int x)
{
if(p[x] != x) p[x] = find(p[x]);
return p[x];
}
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++) p[i] = i;
while(m--)
{
int z, x, y;
cin >> z >> x >> y;
x = find(x);
y = find(y);
if (z == 1)
{
p[x] = y;
}
else
{
if (x != y) puts("N");
else puts("Y");
}
}
return 0;
}
洛谷P8604 [蓝桥杯 2013 国 C] 危险系数
思路:
dfs
搜索,先求出几条路径,在求出每一条路径的时候,经过点都记录一下,最后比较路径数与经过点的次数,如果一样则说明这个点是关键点。
代码:
#include <iostream>
using namespace std;
const int N = 1010;
int g[N][N], cnt[N];
bool st[N*2];
int n, m, start, ed, sum;
void dfs(int u)
{
if (u == ed)
{
sum ++;
for (int i = 1; i <= n; i++)
if (st[i]) cnt [i]++;
return ;
}
for (int i = 1; i <= n; i ++)
{
if(g[i][u] == 1 && !st[i])
{
st[i] = true;
dfs(i);
st[i] = false;
}
}
return ;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= m; i ++)
{
int a, b;
cin >> a >> b;
g[a][b] = g[b][a] = 1;
}
cin >> start >> ed;
dfs(start);
if(sum > 0)
{
int res = 0;
for (int i = 1; i <= n; i ++)
{
if(cnt[i] == sum) res ++;
}
cout << res - 1;
}
else cout << -1;
return 0;
}
洛谷P1330 封锁阳光大学
思路:
用的染色法,但是只过了6个样例,代码并不完美,仍需完善。
代码:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int e[N], ne[N], h[N], idx;
int color[N], n, m, sum[10], ans;
bool st[N];
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
bool dfs(int u, int c)
{
color[u] = c;
sum[c] ++;
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!color[j])
{
if(!dfs(j, 3-c)) return false;
}
else if (color[j] == c) return false;
}
return true;
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
while(m --)
{
int a, b;
cin >> a >> b;
add(a, b);
add(b, a);
}
int flag = true;
for (int i = 1; i <= n; i++)
{
if(!color[i])
{
if(!dfs(i, 1))
{
flag = false;
break;
}
}
ans += min(sum[1], sum[2]);
sum [1] = sum[2] = 0;
}
if(!flag) puts("impossible");
else cout << ans;
return 0;
}
洛谷P3916 图的遍历
思路:
一开始以为就是爆搜每个点能够到达的最大点,但是时间复杂度太高了,看了题解,学会了新的知识——反向建图。
代码:
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
int e[N], ne[N], h[N], idx;
int n, m, ans[N];
bool st[N];
void add(int b, int a)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
void dfs(int u, int a)
{
if(ans[u]) return ;
ans[u] = a;
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if(!st[j])
{
st[j] = true;
dfs(j, a);
st[j] = false;
}
}
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
while(m--)
{
int a, b;
cin >> a >> b;
add(a, b);
}
for (int i = n; i > 0; i --)
{
if(!ans[i]) dfs(i, i);
}
for (int i = 1; i <= n; i ++)
cout << ans[i] << ' ';
return 0;
}