并查集
/*
* 并查集的应用
*
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#define MAXN 1000
int matrix[MAXN][MAXN]; // 定义距离
int parent[MAXN]; // 其父亲节点
using namespace std;
void _init()
{
for( int i=0; i<=999; i++)
{
parent[i]=i;
}
}
int FindParent( int i ) // 找父节点
{
int pos=i;
if(parent[pos]!=pos)
{
parent[pos]=FindParent(parent[pos]); //不要写成死循环
}
return parent[pos];
}
void _union( int x, int y )
{
//
int x1=FindParent(x);
int y1=FindParent(y);
if(x1<y1){
parent[y1]=x1;
}
else
parent[x1]=y1;
}
// 就在做集合的合并时候出现的问题 如果是 parent[pos]=-1 以及parent[pos]=-2;
//没有使用parent[pos]=pos方便
int main()
{
int answer=-1;
int nodeNum;
int edgeNum;
cin>>nodeNum>>edgeNum;
_init();
for( int i=0; i<edgeNum;i++)
{
int pos1,pos2;
cin>>pos1>>pos2;
_union(pos1,pos2);
}
for( int i=0; i<nodeNum;i++)
{
if(parent[i]==i){
answer++;
}
}
cout<<answer;
return 0;
}
那么这段关于并查集的代码, 自己开始parent[]初始化-2 , 判断是否终止使用-2这种方式并不方便, 不如使用parent[ i]=i
最小生成树代码 :
/*
* 最小生成树
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#include<algorithm>
#define MAXN 1000
int parent[MAXN]; //父辈
using namespace std;
struct Edge
{
int from ;
int to;
int weight;
bool operator< ( Edge b)
{
return weight<b.weight;
}
};
struct Edge node[MAXN];
void _init( int n )
{
for( int i =0; i<n; i++)
{
parent[i]=i;
}
}
int Find( int x)
{
if(parent[x]!=x)
{
parent[x]=Find(parent[x]);
}
return parent[x];
}
void _union( int x, int y)
{
int a=Find(x);
int b=Find(y);
if(a<b)
{
parent[a]=b;
}
else
{
parent[b]=a;
}
}
//克鲁斯卡尔算法
int Kruskar( int num)
{
int sum=0;
for( int i =0; i<num; i++) // 边数
{
Edge current= node[i];
if(Find(current.to)!=Find(current.from)) // 并不用使用visit了
{
_union(current.to,current.from);
sum+=current.weight;
}
}
return sum;
}
int main()
{
int n; int num;
cin>>n>>num;
_init(n);
for( int i =0;i<n;i++){
cin>>node[i].to>>node[i].from>>node[i].weight;
}
sort(node,node+n);
cout<<Kruskar(n);
}
最短路径
/*
* 最短路径
看来还是应该考虑一下非连通图的情况
下面的并没有考虑
以下的代码使用vector 存储邻接表来表示图
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#define MAXN 1000
using namespace std;
int dis[MAXN];
struct Edge
{
int to;
int weight;
Edge(int a, int t):to(a),weight(t);
bool operator< ( Edge b)
{
return weight<b.weight;
}
};
vector<Edge>graph[MAXN];
//存储邻接表
struct Node {
int node_num;//节点编号
int distance ;//定义距离
Node( int n ,int d):node_num(n),distance(d);
bool operator <(Node b){
return distance>b.distance;
}
};
struct Edge node[MAXN];
void update( int updateNodeNum){
for( int i =0;i<99;i++){
if(dis[updateNodeNum][i]!=0){
if(dis[0][i]>dis[0][updateNodeNum]+dis[updateNodeNum][i]){
dis[0][i]=dis[0][updateNodeNum]+dis[updateNodeNum][i];
}
}
}
} //随随着节点的加入所有与它相连的都更新
void Dijkstra( int s){
priority_queue<Node>myQueue; //优先队列
dis[s]=0;
myQueue.push(Node(s,dis[s]));
while(!myQueue.empty()){
int u=myQueue.top().node_num;
for( int i =0;i<graph[u].size();i++){
int v=graph[u][i].to;
int d=graph[u][i].length;
if(dis[v]>dis[u]+d){
dis[v]=dis[u]+d;
myQueue.push(Node(v,dis[v]));
//这种写法之后不能用 distance 也可以在做一个 bool visit[]
}
}
}
} // 最短路径算法
int main(){
int n, int m;
while( scanf("%d%d",&n,&m)!=EOF){
memset(graph,0,sizeof(graph));
fill(dis,dis+n,10000);
}
while(m--){
int from ;
int to;
int length;
cin>>from>>to>>length;
graph[from].push_back(Edge(to,length));
graph[to].push_back(Edge(from,length));
int s,t;
cin>>s>>t;
Dijkstra(s)
if(dis[t]==100000){
cout<<"不可达"<<endl;
}
}
return 0;
}
拓扑排序
/*
* DAG :拓扑排序
* 拓扑排序是 利用队列 根据入度以及出度
*
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#define MAXN 1000
using namespace std;
int inDegree[MAXN]; // 定义入度
vector<int> graph[MAXN];
vector<int > TopSort( int n ){ //topSort
vector<int> myQueue; //存放结果
priority_queue<int , vector<int>,greater<int>>node;
for( int i=0;i<=n;i++){
if(inDegree[i]==0){
node.push(i);
//将节点近队列
}
}
while(!node.empty()){ //节点不为空时候
int u=node.top();
node.pop();
myQueue.push(u);//将节点放进去结果中
for( int i =0;i<graph[u].size();i++){
int t=graph[u][i];
inDegree[t]--;
if(inDegree[t]==0){
node.push(t);
}
}
}
return myQueue;
}
void _init( int m){
//完成的任务
int from ;
int to;
while(m--){
cin>>from>>to;
graph[from].push_back(to);
inDegree[to]++;
}
}
int main(){
int n ,m;
cin>>n>>m;
_init(m);
vector<int >result=TopSort(n);
return 0;
}
关键路径
/*
* aov aoe
* 关键路径 最早发生时间&&最晚发生时间
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<map>
#include<vector>
#include<algorithm>
#define MAXN 1000
using namespace std;
int inDegree[MAXN]; // 定义入度
struct Edge
{
int to;
int length;
Edge(int a, int b ):to(a),length(b);
};
queue<int>myQueue;// 求最短事件用的
vector<Edge>graph[MAXN];
int earlyTime[MAXN]; //最早开始时间
int lateTime[MAXN]; //最晚开始时间
queue<int>TopQueue; //存储节点队列含有边的关系
void _init( int m) //边数
{
//完成节点的存储
}
void TopSort( int n ) //返回一个最后事件的发生事件
{
int lastTime;
while(!myQueue.empty())
{
int a=myQueue.top();
myQueue.pop();
TopQueue.push(a);
for(int i =0; i<graph[a].size(); i++)
{
int nodeNum=graph[a][i].to;
int len=graph[a][i].length;
if(earlyTime[a]+len>earlyTime[nodeNum])
{
earlyTime[a]+len=earlyTime[nodeNum];
// 最早时间选择最大的
}
inDegree[nodeNum]--;
if(inDegree[nodeNum]==0)
{
myQueue.push(nodeNum);
}
}
}
for( int j =TopQueue.size()-1; j>=0; j--)
{
// 一定是相反的顺序!
int a =TopQueue[i];
if(graph[a].size()==0){
lateTime[a]=earlyTime[a];
}
for( int k=0;k<graph[a].size()-1;k++){
int v=graph[u][j].to;
int l=graph[u][j].length;
lateTime[u]=min(lateTime[u],lateTime[v]-l);
// 还少一个判断是不是关键路径的
}
}
}
(部分代码 )
随笔
今天查阅资料时候发现servlet类似于spring mvc的一个地方 , 一般而言在写servlet时候 都是继承httpservlet, 利用httpservlet的service方法进而执行doGet或者doPost ,那么也可以自定义个servlet通过复写service方法识别url路径找到确定的字节码对象,进而找到对应的方法对象,执行方法
(这次操作真是惊到了我 真是万物皆对象 ,不由得让我想起了函数指针)