1.B3647 【模板】Floyd
这个Floyd算法蒟蒻也似懂非懂,建议去看本题题解: B3647 【模板】Floyd - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/solution/B3647
#include
using namespace std;
int n,m,u,v,w;
int Map[105][105],g[105][105];
int main()
{
cin>>n>>m;
//初始化
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(i == j) Map[i][j] = 0;
else{
Map[i][j] = 1e9;
Map[j][i] = 1e9;
}
}
//存图
for(int i=0;i>u>>v>>w;
Map[u][v] = min(Map[u][v],w);
Map[v][u] = Map[u][v];
}
for(int k=1;k<=n;k++){
for(int u=1;u<=n;u++){
for(int v=1;v<=n;v++){
Map[u][v] = min(Map[u][v],Map[u][k]+Map[k][v]);
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)
cout<
2.P4779 【模板】单源最短路径(标准版)
堆优化蒟蒻也不太懂,就不瞎解释了。
迪杰斯特拉dijkstra算法,重点——松弛操作!其余请看图(
#include
const int MaxN = 100010, MaxM = 500010;
struct edge
{
int to, dis, next;
};
edge e[MaxM];
int head[MaxN], dis[MaxN], cnt;
bool vis[MaxN];
int n, m, s;
inline void add_edge( int u, int v, int d )
{
cnt++;
e[cnt].dis = d;
e[cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt;
}
struct node
{
int dis;
int pos;
bool operator <( const node &x )const
{
return x.dis < dis;
}
};
std::priority_queue q;
inline void dijkstra()
{
dis[s] = 0;
q.push( ( node ){0, s} );
while( !q.empty() )
{
node tmp = q.top();
q.pop();
int x = tmp.pos, d = tmp.dis;
if( vis[x] )
continue;
vis[x] = 1;
for( int i = head[x]; i; i = e[i].next )
{
int y = e[i].to;
if( dis[y] > dis[x] + e[i].dis )
{
dis[y] = dis[x] + e[i].dis;
if( !vis[y] )
{
q.push( ( node ){dis[y], y} );
}
}
}
}
}
int main()
{
scanf( "%d%d%d", &n, &m, &s );
for(int i = 1; i <= n; ++i)dis[i] = 0x7fffffff;
for( register int i = 0; i < m; ++i )
{
register int u, v, d;
scanf( "%d%d%d", &u, &v, &d );
add_edge( u, v, d );
}
dijkstra();
for( int i = 1; i <= n; i++ )
printf( "%d ", dis[i] );
return 0;
}
3.P2661 [NOIP2015 提高组] 信息传递
并查集求最小环:并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。比如说,我们可以用并查集来判断一个森林中有几棵树、某个节点是否属于某棵树等。
把每个同学看成一个节点,信息传递为一条有向边,游戏轮数即为最小环。
#include
using namespace std;
const int MAX_N = 2e5+5;
int n,T[MAX_N],f[MAX_N],cnt[MAX_N];//f[]保存祖先节点,cnt[]保存到祖先的路径长
int min_x = 0x7777777;
int father(int x)//用于查找祖先节点
{
if(f[x] != x){
int fa = f[x];//记录父节点,防止被递归更新掉
f[x] = father(f[x]);//更新祖先节点
cnt[x] += cnt[fa];
}
return f[x];
}
void check(int a,int b)
{
int x = father(a),y = father(b);//查找祖先节点
if(x != y){//若不相连,则连接两点,更新父节点和路径长。
f[x] = y;
cnt[a] = cnt[b]+1;
}
else//若已连接,则更新最小环长度。
min_x = min(min_x,cnt[a]+cnt[b]+1);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) f[i] = i;//父节点初始化为自己,cnt=0
for(int i=1;i<=n;i++)
scanf("%d",&T[i]);
for(int i=1;i<=n;i++){
check(i,T[i]);
}
printf("%d",min_x);
return 0;
}
4.P1144 最短路计数
在题解中看到一个新奇的思路,无权无向图中,顶点到某个节点的最短路就是其BFS搜索树的深度。
#include
using namespace std;
const int maxn=1e6+5,maxm=2e6+5,mod=100003;
int n,m;
vector Map[maxn];
int deep[maxn],cnt[maxn],vis[maxn];//deep[]当前顶点到第i点的深度,cnt[]顶点到第i点的min深度,vis[]标记某点是否来过
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
Map[x].push_back(y);
Map[y].push_back(x);//无向图存图
}
queue q;
//初始化
deep[1] = 0;
vis[1] = 0;
q.push(1);
cnt[1] = 1;
while(!q.empty()){
int x = q.front();
q.pop();
for(int i=0;i
5.P8794 [蓝桥杯 2022 国 A] 环境治理
原题指路:P8794 [蓝桥杯 2022 国 A] 环境治理 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P8794
二分+最短路
二分:每治理一次,P值都会下降,为单调递减,可用二分。
最短路:floyd算法,详见第一题。
#include
using namespace std;
#define inf 0x7777777
int n,q,ans=-1;
long long d[105][105],l[105][105];
int cal(int x)//计算治理x天后的P值
{
int temp[105][105];
for(int i=0;i=i+1) a = 1;
else a = 0;
int b = x/n+a;
for(int j=0;j>n>>q;
for(int i=0;i>d[i][j];
for(int i=0;i>l[i][j];
int left=0,right=inf;
while(left<=right){//二分求治理天数
int mid = (left+right)/2;
if(cal(mid)<=q){
right = mid-1;
ans = mid;
}
else
left = mid+1;
}
cout<